Init TEngine4.0.0

Init TEngine4.0.0
This commit is contained in:
ALEXTANG
2023-10-08 15:21:33 +08:00
parent 4c8c37ffd8
commit 8c3d6308b9
3773 changed files with 49313 additions and 150734 deletions

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEditor;
namespace YooAsset.Editor
{
public static class ShaderVariantCollectionHelper
{
public static void ClearCurrentShaderVariantCollection()
{
EditorTools.InvokeNonPublicStaticMethod(typeof(ShaderUtil), "ClearCurrentShaderVariantCollection");
}
public static void SaveCurrentShaderVariantCollection(string savePath)
{
EditorTools.InvokeNonPublicStaticMethod(typeof(ShaderUtil), "SaveCurrentShaderVariantCollection", savePath);
}
public static int GetCurrentShaderVariantCollectionShaderCount()
{
return (int)EditorTools.InvokeNonPublicStaticMethod(typeof(ShaderUtil), "GetCurrentShaderVariantCollectionShaderCount");
}
public static int GetCurrentShaderVariantCollectionVariantCount()
{
return (int)EditorTools.InvokeNonPublicStaticMethod(typeof(ShaderUtil), "GetCurrentShaderVariantCollectionVariantCount");
}
/// <summary>
/// 获取着色器的变种总数量
/// </summary>
public static string GetShaderVariantCount(string assetPath)
{
Shader shader = AssetDatabase.LoadAssetAtPath<Shader>(assetPath);
var variantCount = EditorTools.InvokeNonPublicStaticMethod(typeof(ShaderUtil), "GetVariantCount", shader, true);
return variantCount.ToString();
}
}
}

View File

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

View File

@@ -0,0 +1,149 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEditor;
namespace YooAsset.Editor
{
[Serializable]
public class ShaderVariantCollectionManifest
{
[Serializable]
public class ShaderVariantElement
{
/// <summary>
/// Pass type to use in this variant.
/// </summary>
public PassType PassType;
/// <summary>
/// Array of shader keywords to use in this variant.
/// </summary>
public string[] Keywords;
}
[Serializable]
public class ShaderVariantInfo
{
/// <summary>
/// 着色器资源路径.
/// </summary>
public string AssetPath;
/// <summary>
/// 着色器名称
/// </summary>
public string ShaderName;
/// <summary>
/// 着色器变种总数
/// </summary>
public int ShaderVariantCount = 0;
/// <summary>
/// 着色器变种列表
/// </summary>
public List<ShaderVariantElement> ShaderVariantElements = new List<ShaderVariantElement>(1000);
}
/// <summary>
/// Number of shaders in this collection
/// </summary>
public int ShaderTotalCount;
/// <summary>
/// Number of total varians in this collection
/// </summary>
public int VariantTotalCount;
/// <summary>
/// Shader variants info list.
/// </summary>
public List<ShaderVariantInfo> ShaderVariantInfos = new List<ShaderVariantInfo>(1000);
/// <summary>
/// 添加着色器变种信息
/// </summary>
public void AddShaderVariant(string assetPath, string shaderName, PassType passType, string[] keywords)
{
var info = GetOrCreateShaderVariantInfo(assetPath, shaderName);
ShaderVariantElement element = new ShaderVariantElement();
element.PassType = passType;
element.Keywords = keywords;
info.ShaderVariantElements.Add(element);
info.ShaderVariantCount++;
}
private ShaderVariantInfo GetOrCreateShaderVariantInfo(string assetPath, string shaderName)
{
var selectList = ShaderVariantInfos.Where(t => t.ShaderName == shaderName && t.AssetPath == assetPath).ToList();
if (selectList.Count == 0)
{
ShaderVariantInfo newInfo = new ShaderVariantInfo();
newInfo.AssetPath = assetPath;
newInfo.ShaderName = shaderName;
ShaderVariantInfos.Add(newInfo);
return newInfo;
}
if (selectList.Count != 1)
throw new Exception("Should never get here !");
return selectList[0];
}
/// <summary>
/// 解析SVC文件并将数据写入到清单
/// </summary>
public static ShaderVariantCollectionManifest Extract(ShaderVariantCollection svc)
{
var manifest = new ShaderVariantCollectionManifest();
manifest.ShaderTotalCount = ShaderVariantCollectionHelper.GetCurrentShaderVariantCollectionShaderCount();
manifest.VariantTotalCount = ShaderVariantCollectionHelper.GetCurrentShaderVariantCollectionVariantCount();
using (var so = new SerializedObject(svc))
{
var shaderArray = so.FindProperty("m_Shaders.Array");
if (shaderArray != null && shaderArray.isArray)
{
for (int i = 0; i < shaderArray.arraySize; ++i)
{
var shaderRef = shaderArray.FindPropertyRelative($"data[{i}].first");
var shaderVariantsArray = shaderArray.FindPropertyRelative($"data[{i}].second.variants");
if (shaderRef != null && shaderRef.propertyType == SerializedPropertyType.ObjectReference && shaderVariantsArray != null && shaderVariantsArray.isArray)
{
var shader = shaderRef.objectReferenceValue as Shader;
if (shader == null)
{
throw new Exception("Invalid shader in ShaderVariantCollection file.");
}
string shaderAssetPath = AssetDatabase.GetAssetPath(shader);
string shaderName = shader.name;
// 添加变种信息
for (int j = 0; j < shaderVariantsArray.arraySize; ++j)
{
var propKeywords = shaderVariantsArray.FindPropertyRelative($"Array.data[{j}].keywords");
var propPassType = shaderVariantsArray.FindPropertyRelative($"Array.data[{j}].passType");
if (propKeywords != null && propPassType != null && propKeywords.propertyType == SerializedPropertyType.String)
{
string[] keywords = propKeywords.stringValue.Split(' ');
PassType pathType = (PassType)propPassType.intValue;
manifest.AddShaderVariant(shaderAssetPath, shaderName, pathType, keywords);
}
}
}
}
}
}
return manifest;
}
}
}

View File

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

View File

@@ -0,0 +1,258 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.IO;
using UnityEngine;
using UnityEditor;
using UnityEditor.SceneManagement;
using Debug = UnityEngine.Debug;
namespace YooAsset.Editor
{
public static class ShaderVariantCollector
{
private enum ESteps
{
None,
Prepare,
CollectAllMaterial,
CollectVariants,
CollectSleeping,
WaitingDone,
}
private const float WaitMilliseconds = 1000f;
private const float SleepMilliseconds = 100f;
private static string _savePath;
private static string _packageName;
private static int _processMaxNum;
private static Action _completedCallback;
private static ESteps _steps = ESteps.None;
private static Stopwatch _elapsedTime;
private static List<string> _allMaterials;
private static List<GameObject> _allSpheres = new List<GameObject>(1000);
/// <summary>
/// 开始收集
/// </summary>
public static void Run(string savePath, string packageName, int processMaxNum, Action completedCallback)
{
if (_steps != ESteps.None)
return;
if (Path.HasExtension(savePath) == false)
savePath = $"{savePath}.shadervariants";
if (Path.GetExtension(savePath) != ".shadervariants")
throw new System.Exception("Shader variant file extension is invalid.");
if (string.IsNullOrEmpty(packageName))
throw new System.Exception("Package name is null or empty !");
// 注意先删除再保存否则ShaderVariantCollection内容将无法及时刷新
AssetDatabase.DeleteAsset(savePath);
EditorTools.CreateFileDirectory(savePath);
_savePath = savePath;
_packageName = packageName;
_processMaxNum = processMaxNum;
_completedCallback = completedCallback;
// 聚焦到游戏窗口
EditorTools.FocusUnityGameWindow();
// 创建临时测试场景
CreateTempScene();
_steps = ESteps.Prepare;
EditorApplication.update += EditorUpdate;
}
private static void EditorUpdate()
{
if (_steps == ESteps.None)
return;
if (_steps == ESteps.Prepare)
{
ShaderVariantCollectionHelper.ClearCurrentShaderVariantCollection();
_steps = ESteps.CollectAllMaterial;
return; //等待一帧
}
if (_steps == ESteps.CollectAllMaterial)
{
_allMaterials = GetAllMaterials();
_steps = ESteps.CollectVariants;
return; //等待一帧
}
if (_steps == ESteps.CollectVariants)
{
int count = Mathf.Min(_processMaxNum, _allMaterials.Count);
List<string> range = _allMaterials.GetRange(0, count);
_allMaterials.RemoveRange(0, count);
CollectVariants(range);
if (_allMaterials.Count > 0)
{
_elapsedTime = Stopwatch.StartNew();
_steps = ESteps.CollectSleeping;
}
else
{
_elapsedTime = Stopwatch.StartNew();
_steps = ESteps.WaitingDone;
}
}
if (_steps == ESteps.CollectSleeping)
{
if (_elapsedTime.ElapsedMilliseconds > SleepMilliseconds)
{
DestroyAllSpheres();
_elapsedTime.Stop();
_steps = ESteps.CollectVariants;
}
}
if (_steps == ESteps.WaitingDone)
{
// 注意:一定要延迟保存才会起效
if (_elapsedTime.ElapsedMilliseconds > WaitMilliseconds)
{
_elapsedTime.Stop();
_steps = ESteps.None;
// 保存结果并创建清单
ShaderVariantCollectionHelper.SaveCurrentShaderVariantCollection(_savePath);
CreateManifest();
Debug.Log($"搜集SVC完毕");
EditorApplication.update -= EditorUpdate;
_completedCallback?.Invoke();
}
}
}
private static void CreateTempScene()
{
EditorSceneManager.NewScene(NewSceneSetup.DefaultGameObjects);
}
private static List<string> GetAllMaterials()
{
int progressValue = 0;
List<string> allAssets = new List<string>(1000);
// 获取所有打包的资源
CollectResult collectResult = AssetBundleCollectorSettingData.Setting.GetPackageAssets(EBuildMode.DryRunBuild, _packageName);
foreach (var assetInfo in collectResult.CollectAssets)
{
string[] depends = AssetDatabase.GetDependencies(assetInfo.AssetPath, true);
foreach (var dependAsset in depends)
{
if (allAssets.Contains(dependAsset) == false)
allAssets.Add(dependAsset);
}
EditorTools.DisplayProgressBar("获取所有打包资源", ++progressValue, collectResult.CollectAssets.Count);
}
EditorTools.ClearProgressBar();
// 搜集所有材质球
progressValue = 0;
List<string> allMaterial = new List<string>(1000);
foreach (var assetPath in allAssets)
{
System.Type assetType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
if (assetType == typeof(UnityEngine.Material))
{
allMaterial.Add(assetPath);
}
EditorTools.DisplayProgressBar("搜集所有材质球", ++progressValue, allAssets.Count);
}
EditorTools.ClearProgressBar();
// 返回结果
return allMaterial;
}
private static void CollectVariants(List<string> materials)
{
Camera camera = Camera.main;
if (camera == null)
throw new System.Exception("Not found main camera.");
// 设置主相机
float aspect = camera.aspect;
int totalMaterials = materials.Count;
float height = Mathf.Sqrt(totalMaterials / aspect) + 1;
float width = Mathf.Sqrt(totalMaterials / aspect) * aspect + 1;
float halfHeight = Mathf.CeilToInt(height / 2f);
float halfWidth = Mathf.CeilToInt(width / 2f);
camera.orthographic = true;
camera.orthographicSize = halfHeight;
camera.transform.position = new Vector3(0f, 0f, -10f);
// 创建测试球体
int xMax = (int)(width - 1);
int x = 0, y = 0;
int progressValue = 0;
for (int i = 0; i < materials.Count; i++)
{
var material = materials[i];
var position = new Vector3(x - halfWidth + 1f, y - halfHeight + 1f, 0f);
var go = CreateSphere(material, position, i);
if (go != null)
_allSpheres.Add(go);
if (x == xMax)
{
x = 0;
y++;
}
else
{
x++;
}
EditorTools.DisplayProgressBar("照射所有材质球", ++progressValue, materials.Count);
}
EditorTools.ClearProgressBar();
}
private static GameObject CreateSphere(string assetPath, Vector3 position, int index)
{
var material = AssetDatabase.LoadAssetAtPath<Material>(assetPath);
var shader = material.shader;
if (shader == null)
return null;
var go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
go.GetComponent<Renderer>().sharedMaterial = material;
go.transform.position = position;
go.name = $"Sphere_{index} | {material.name}";
return go;
}
private static void DestroyAllSpheres()
{
foreach(var go in _allSpheres)
{
GameObject.DestroyImmediate(go);
}
_allSpheres.Clear();
// 尝试释放编辑器加载的资源
EditorUtility.UnloadUnusedAssetsImmediate(true);
}
private static void CreateManifest()
{
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
ShaderVariantCollection svc = AssetDatabase.LoadAssetAtPath<ShaderVariantCollection>(_savePath);
if (svc != null)
{
var wrapper = ShaderVariantCollectionManifest.Extract(svc);
string jsonData = JsonUtility.ToJson(wrapper, true);
string savePath = _savePath.Replace(".shadervariants", ".json");
File.WriteAllText(savePath, jsonData);
}
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
}
}
}

View File

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

View File

@@ -0,0 +1,23 @@
using UnityEngine;
namespace YooAsset.Editor
{
[CreateAssetMenu(fileName = "ShaderVariantCollectorSetting", menuName = "YooAsset/Create ShaderVariant Collector Settings")]
public class ShaderVariantCollectorSetting : ScriptableObject
{
/// <summary>
/// 文件存储路径
/// </summary>
public string SavePath = "Assets/MyShaderVariants.shadervariants";
/// <summary>
/// 收集的包裹名称
/// </summary>
public string CollectPackage = string.Empty;
/// <summary>
/// 容器值
/// </summary>
public int ProcessCapacity = 1000;
}
}

View File

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

View File

@@ -0,0 +1,49 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace YooAsset.Editor
{
public class ShaderVariantCollectorSettingData
{
private static ShaderVariantCollectorSetting _setting = null;
public static ShaderVariantCollectorSetting Setting
{
get
{
if (_setting == null)
LoadSettingData();
return _setting;
}
}
/// <summary>
/// 配置数据是否被修改
/// </summary>
public static bool IsDirty { set; get; } = false;
/// <summary>
/// 加载配置文件
/// </summary>
private static void LoadSettingData()
{
_setting = SettingLoader.LoadSettingData<ShaderVariantCollectorSetting>();
}
/// <summary>
/// 存储文件
/// </summary>
public static void SaveFile()
{
if (Setting != null)
{
IsDirty = false;
EditorUtility.SetDirty(Setting);
AssetDatabase.SaveAssets();
Debug.Log($"{nameof(ShaderVariantCollectorSetting)}.asset is saved!");
}
}
}
}

View File

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

View File

@@ -0,0 +1,185 @@
#if UNITY_2019_4_OR_NEWER
using System;
using System.Linq;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
namespace YooAsset.Editor
{
public class ShaderVariantCollectorWindow : EditorWindow
{
[MenuItem("YooAsset/ShaderVariant Collector", false, 201)]
public static void OpenWindow()
{
ShaderVariantCollectorWindow window = GetWindow<ShaderVariantCollectorWindow>("着色器变种收集工具", true, WindowsDefine.DockedWindowTypes);
window.minSize = new Vector2(800, 600);
}
private List<string> _packageNames;
private Button _saveButton;
private Button _collectButton;
private TextField _collectOutputField;
private Label _currentShaderCountField;
private Label _currentVariantCountField;
private SliderInt _processCapacitySlider;
private PopupField<string> _packageField;
public void CreateGUI()
{
try
{
VisualElement root = this.rootVisualElement;
// 加载布局文件
var visualAsset = UxmlLoader.LoadWindowUXML<ShaderVariantCollectorWindow>();
if (visualAsset == null)
return;
visualAsset.CloneTree(root);
// 配置保存按钮
_saveButton = root.Q<Button>("SaveButton");
_saveButton.clicked += SaveBtn_clicked;
// 包裹名称列表
_packageNames = GetBuildPackageNames();
// 文件输出目录
_collectOutputField = root.Q<TextField>("CollectOutput");
_collectOutputField.SetValueWithoutNotify(ShaderVariantCollectorSettingData.Setting.SavePath);
_collectOutputField.RegisterValueChangedCallback(evt =>
{
ShaderVariantCollectorSettingData.IsDirty = true;
ShaderVariantCollectorSettingData.Setting.SavePath = _collectOutputField.value;
});
// 收集的包裹
var packageContainer = root.Q("PackageContainer");
if (_packageNames.Count > 0)
{
int defaultIndex = GetDefaultPackageIndex(ShaderVariantCollectorSettingData.Setting.CollectPackage);
_packageField = new PopupField<string>(_packageNames, defaultIndex);
_packageField.label = "Package";
_packageField.style.width = 350;
_packageField.RegisterValueChangedCallback(evt =>
{
ShaderVariantCollectorSettingData.IsDirty = true;
ShaderVariantCollectorSettingData.Setting.CollectPackage = _packageField.value;
});
packageContainer.Add(_packageField);
}
else
{
_packageField = new PopupField<string>();
_packageField.label = "Package";
_packageField.style.width = 350;
packageContainer.Add(_packageField);
}
// 容器值
_processCapacitySlider = root.Q<SliderInt>("ProcessCapacity");
_processCapacitySlider.SetValueWithoutNotify(ShaderVariantCollectorSettingData.Setting.ProcessCapacity);
#if !UNITY_2020_3_OR_NEWER
_processCapacitySlider.label = $"Capacity ({_processCapacitySlider.value})";
_processCapacitySlider.RegisterValueChangedCallback(evt =>
{
ShaderVariantCollectorSettingData.IsDirty = true;
ShaderVariantCollectorSettingData.Setting.ProcessCapacity = _processCapacitySlider.value;
_processCapacitySlider.label = $"Capacity ({_processCapacitySlider.value})";
});
#else
_processCapacitySlider.RegisterValueChangedCallback(evt =>
{
ShaderVariantCollectorSettingData.IsDirty = true;
ShaderVariantCollectorSettingData.Setting.ProcessCapacity = _processCapacitySlider.value;
});
#endif
_currentShaderCountField = root.Q<Label>("CurrentShaderCount");
_currentVariantCountField = root.Q<Label>("CurrentVariantCount");
// 变种收集按钮
_collectButton = root.Q<Button>("CollectButton");
_collectButton.clicked += CollectButton_clicked;
}
catch (Exception e)
{
Debug.LogError(e.ToString());
}
}
public void OnDestroy()
{
if (ShaderVariantCollectorSettingData.IsDirty)
ShaderVariantCollectorSettingData.SaveFile();
}
private void Update()
{
if (_saveButton != null)
{
if (ShaderVariantCollectorSettingData.IsDirty)
{
if (_saveButton.enabledSelf == false)
_saveButton.SetEnabled(true);
}
else
{
if (_saveButton.enabledSelf)
_saveButton.SetEnabled(false);
}
}
if (_currentShaderCountField != null)
{
int currentShaderCount = ShaderVariantCollectionHelper.GetCurrentShaderVariantCollectionShaderCount();
_currentShaderCountField.text = $"Current Shader Count : {currentShaderCount}";
}
if (_currentVariantCountField != null)
{
int currentVariantCount = ShaderVariantCollectionHelper.GetCurrentShaderVariantCollectionVariantCount();
_currentVariantCountField.text = $"Current Variant Count : {currentVariantCount}";
}
}
private void SaveBtn_clicked()
{
ShaderVariantCollectorSettingData.SaveFile();
}
private void CollectButton_clicked()
{
string savePath = ShaderVariantCollectorSettingData.Setting.SavePath;
string packageName = ShaderVariantCollectorSettingData.Setting.CollectPackage;
int processCapacity = _processCapacitySlider.value;
ShaderVariantCollector.Run(savePath, packageName, processCapacity, null);
}
// 构建包裹相关
private int GetDefaultPackageIndex(string packageName)
{
for (int index = 0; index < _packageNames.Count; index++)
{
if (_packageNames[index] == packageName)
{
return index;
}
}
ShaderVariantCollectorSettingData.Setting.CollectPackage = _packageNames[0];
return 0;
}
private List<string> GetBuildPackageNames()
{
List<string> result = new List<string>();
foreach (var package in AssetBundleCollectorSettingData.Setting.Packages)
{
result.Add(package.PackageName);
}
return result;
}
}
}
#endif

View File

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

View File

@@ -0,0 +1,13 @@
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="False">
<uie:Toolbar name="Toolbar" style="display: flex; flex-direction: row-reverse;">
<ui:Button text="Save" display-tooltip-when-elided="true" name="SaveButton" style="background-color: rgb(40, 106, 42);" />
</uie:Toolbar>
<ui:VisualElement name="CollectContainer">
<ui:TextField picking-mode="Ignore" label="文件保存路径" name="CollectOutput" style="height: 22px;" />
<ui:VisualElement name="PackageContainer" style="height: 24px;" />
<ui:Label text="Current Shader Count" display-tooltip-when-elided="true" name="CurrentShaderCount" style="height: 20px; padding-left: 4px;" />
<ui:Label text="Current Variant Count" display-tooltip-when-elided="true" name="CurrentVariantCount" style="height: 20px; padding-left: 4px;" />
<ui:SliderInt picking-mode="Ignore" label="Capacity" value="9999" high-value="1000" name="ProcessCapacity" low-value="10" show-input-field="true" />
<ui:Button text="开始搜集" display-tooltip-when-elided="true" name="CollectButton" style="height: 50px; background-color: rgb(40, 106, 42); margin-top: 10px;" />
</ui:VisualElement>
</ui:UXML>

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 9bff4878063eaf04dab8713e1e662ac5
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}