void AddVariants(Shader shader, string assetPath, int id, List <ShaderVariantData> shaderVariants, Action <ProjectIssue> onIssueFound) { var shaderName = shader.name; var descriptor = new ProblemDescriptor ( id++, shaderName ); foreach (var shaderVariantData in shaderVariants) { var compilerData = shaderVariantData.compilerData; var keywords = GetShaderKeywords(shader, compilerData.shaderKeywordSet.GetShaderKeywords()); var issue = new ProjectIssue(descriptor, shaderName, IssueCategory.ShaderVariants, new Location(assetPath)); issue.SetCustomProperties(new string[(int)ShaderVariantProperty.Num] { k_NoRuntimeData, compilerData.shaderCompilerPlatform.ToString(), shaderVariantData.passName, KeywordsToString(keywords), compilerData.shaderRequirements.ToString() }); onIssueFound(issue); } }
private static void AnalyzePackedAssets(Action <ProjectIssue> onIssueFound, BuildReport buildReport) { foreach (var packedAsset in buildReport.packedAssets) { // note that there can be several entries for each source asset (for example, a prefab can reference a Texture, a Material and a shader) var dict = new Dictionary <GUID, List <PackedAssetInfo> >(); foreach (var content in packedAsset.contents) { var assetPath = content.sourceAssetPath; if (!Path.HasExtension(assetPath)) { continue; } if (Path.GetExtension(assetPath).Equals(".cs")) { continue; } if (!dict.ContainsKey(content.sourceAssetGUID)) { dict.Add(content.sourceAssetGUID, new List <PackedAssetInfo>()); } dict[content.sourceAssetGUID].Add(content); } foreach (var entry in dict) { var content = entry.Value[0]; // sourceAssets are the same for all entries var assetPath = content.sourceAssetPath; ulong sum = 0; foreach (var v in entry.Value) { sum += v.packedSize; } var assetName = Path.GetFileNameWithoutExtension(assetPath); string description; if (entry.Value.Count > 1) { description = string.Format("{0} ({1})", assetName, entry.Value.Count); } else { description = assetName; } var issue = new ProjectIssue(k_Descriptor, description, IssueCategory.BuildFiles, new Location(assetPath)); issue.SetCustomProperties(new[] { sum.ToString(), packedAsset.shortPath }); onIssueFound(issue); } } }
public void CustomPropertiesAreSet() { string[] properties = { "property #0", "property #1" }; var issue = new ProjectIssue(s_Descriptor, "dummy issue", IssueCategory.Code); issue.SetCustomProperties(properties); Assert.True(issue.GetCustomProperty(0).Equals(properties[0])); Assert.True(issue.GetCustomProperty(1).Equals(properties[1])); }
void AddVariants(Shader shader, string assetPath, int id, List <ShaderVariantData> shaderVariants, Action <ProjectIssue> onIssueFound) { var shaderName = shader.name; var descriptor = new ProblemDescriptor ( id++, shaderName, Area.BuildSize, string.Empty, string.Empty ); foreach (var shaderVariantData in shaderVariants) { var compilerData = shaderVariantData.compilerData; var shaderKeywordSet = compilerData.shaderKeywordSet.GetShaderKeywords().ToArray(); #if UNITY_2019_3_OR_NEWER var keywords = shaderKeywordSet.Select(keyword => ShaderKeyword.IsKeywordLocal(keyword) ? ShaderKeyword.GetKeywordName(shader, keyword) : ShaderKeyword.GetGlobalKeywordName(keyword)).ToArray(); #else var keywords = shaderKeywordSet.Select(keyword => keyword.GetKeywordName()).ToArray(); #endif var keywordString = String.Join(", ", keywords); if (string.IsNullOrEmpty(keywordString)) { keywordString = "<no keywords>"; } var issue = new ProjectIssue(descriptor, shaderName, IssueCategory.ShaderVariants, new Location(assetPath)); issue.SetCustomProperties(new[] { compilerData.shaderCompilerPlatform.ToString(), shaderVariantData.passName, keywordString, }); onIssueFound(issue); } }
void AddShader(Shader shader, string assetPath, int id, Action <ProjectIssue> onIssueFound) { // set initial state (-1: info not available) var variantCount = s_ShaderVariantData.Count > 0 ? 0 : -1; #if UNITY_2018_2_OR_NEWER // add variants first if (s_ShaderVariantData.ContainsKey(shader)) { var variants = s_ShaderVariantData[shader]; variantCount = variants.Count; AddVariants(shader, assetPath, id++, variants, onIssueFound); } #endif var shaderName = shader.name; var shaderHasError = false; #if UNITY_2019_4_OR_NEWER shaderHasError = ShaderUtil.ShaderHasError(shader); #endif if (shaderHasError) { shaderName = Path.GetFileNameWithoutExtension(assetPath) + ": Parse Error"; var issueWithError = new ProjectIssue(k_ParseErrorDescriptor, shaderName, IssueCategory.Shaders, new Location(assetPath)); issueWithError.SetCustomProperties((int)ShaderProperty.Num, k_NotAvailable); onIssueFound(issueWithError); return; } var descriptor = new ProblemDescriptor ( id++, shaderName ); /* * var usedBySceneOnly = false; * if (m_GetShaderVariantCountMethod != null) * { * var value = (ulong)m_GetShaderVariantCountMethod.Invoke(null, new object[] { shader, usedBySceneOnly}); * variantCount = value.ToString(); * } */ var passCount = -1; var globalKeywords = ShaderUtilProxy.GetShaderGlobalKeywords(shader); var localKeywords = ShaderUtilProxy.GetShaderLocalKeywords(shader); var hasInstancing = ShaderUtilProxy.HasInstancing(shader); var subShaderIndex = ShaderUtilProxy.GetShaderActiveSubshaderIndex(shader); var isSrpBatcherCompatible = ShaderUtilProxy.GetSRPBatcherCompatibilityCode(shader, subShaderIndex) == 0; #if UNITY_2019_1_OR_NEWER passCount = shader.passCount; #endif var issue = new ProjectIssue(descriptor, shaderName, IssueCategory.Shaders, new Location(assetPath)); issue.SetCustomProperties(new string[(int)ShaderProperty.Num] { variantCount == -1 ? k_NotAvailable : variantCount.ToString(), passCount == -1 ? k_NotAvailable : passCount.ToString(), (globalKeywords == null || localKeywords == null) ? k_NotAvailable : (globalKeywords.Length + localKeywords.Length).ToString(), shader.renderQueue.ToString(), hasInstancing.ToString(), isSrpBatcherCompatible.ToString() }); onIssueFound(issue); }
public void Audit(Action <ProjectIssue> onIssueFound, Action onComplete, IProgressBar progressBar = null) { var shaderPathMap = new Dictionary <Shader, string>(); var shaderGuids = AssetDatabase.FindAssets("t:shader"); foreach (var guid in shaderGuids) { var assetPath = AssetDatabase.GUIDToAssetPath(guid); // skip editor shaders if (assetPath.IndexOf("/editor/", StringComparison.OrdinalIgnoreCase) != -1) { continue; } // vfx shaders are not currently supported if (Path.HasExtension(assetPath) && Path.GetExtension(assetPath).Equals(".vfx")) { continue; } var shader = AssetDatabase.LoadMainAssetAtPath(assetPath) as Shader; shaderPathMap.Add(shader, assetPath); } var id = k_ShaderVariantFirstId; if (s_ShaderVariantData == null) { var descriptor = new ProblemDescriptor ( id++, "Shader Variants analysis incomplete", Area.BuildSize, string.Empty, string.Empty ); var message = "Build the project to view the Shader Variants"; #if !UNITY_2018_2_OR_NEWER message = "This feature requires Unity 2018.2 or newer"; #endif var issue = new ProjectIssue(descriptor, message, IssueCategory.ShaderVariants); issue.SetCustomProperties(new[] { string.Empty, string.Empty, string.Empty }); onIssueFound(issue); } else { #if UNITY_2018_2_OR_NEWER // find hidden shaders var shadersInBuild = s_ShaderVariantData.Select(variant => variant.Key); foreach (var shader in shadersInBuild) { // skip shader if it's been removed since the last build if (shader == null) { continue; } if (!shaderPathMap.ContainsKey(shader)) { var assetPath = AssetDatabase.GetAssetPath(shader); shaderPathMap.Add(shader, assetPath); } } #endif } var sortedShaders = shaderPathMap.Keys.ToList().OrderBy(shader => shader.name); foreach (var shader in sortedShaders) { var assetPath = shaderPathMap[shader]; AddShader(shader, assetPath, id++, onIssueFound); } onComplete(); }
void AddShader(Shader shader, string assetPath, int id, Action <ProjectIssue> onIssueFound) { const string NotAvailable = "N/A"; var variantCount = NotAvailable; #if UNITY_2018_2_OR_NEWER // add variants first if (s_ShaderVariantData != null) { if (s_ShaderVariantData.ContainsKey(shader)) { var variants = s_ShaderVariantData[shader]; variantCount = variants.Count.ToString(); AddVariants(shader, assetPath, id++, variants, onIssueFound); } else { variantCount = "0"; } } #endif var shaderName = shader.name; var descriptor = new ProblemDescriptor ( id++, shaderName, Area.BuildSize, string.Empty, string.Empty ); var passCount = NotAvailable; var keywordCount = NotAvailable; var hasInstancing = NotAvailable; /* * var usedBySceneOnly = false; * if (m_GetShaderVariantCountMethod != null) * { * var value = (ulong)m_GetShaderVariantCountMethod.Invoke(null, new object[] { shader, usedBySceneOnly}); * variantCount = value.ToString(); * } */ if (m_GetShaderGlobalKeywordsMethod != null && m_GetShaderLocalKeywordsMethod != null) { var globalKeywords = (string[])m_GetShaderGlobalKeywordsMethod.Invoke(null, new object[] { shader }); var localKeywords = (string[])m_GetShaderLocalKeywordsMethod.Invoke(null, new object[] { shader }); keywordCount = (globalKeywords.Length + localKeywords.Length).ToString(); } if (m_HasInstancingMethod != null) { var value = (bool)m_HasInstancingMethod.Invoke(null, new object[] { shader }); hasInstancing = value ? "Yes" : "No"; } #if UNITY_2019_1_OR_NEWER passCount = shader.passCount.ToString(); #endif var issue = new ProjectIssue(descriptor, shader.name, IssueCategory.Shaders, new Location(assetPath)); issue.SetCustomProperties(new[] { variantCount, passCount, keywordCount, shader.renderQueue.ToString(), hasInstancing, }); onIssueFound(issue); }
public void Audit(Action <ProjectIssue> onIssueFound, Action onComplete, IProgressBar progressBar = null) { var id = k_ShaderVariantFirstId; if (s_ShaderCompilerData == null) { var descriptor = new ProblemDescriptor ( id, "Shader analysis incomplete", Area.BuildSize, string.Empty, string.Empty ); var message = "Build the project and run Project Auditor analysis"; #if !UNITY_2018_2_OR_NEWER message = "This feature requires Unity 2018"; #endif var issue = new ProjectIssue(descriptor, message, IssueCategory.Shaders); issue.SetCustomProperties(new[] { string.Empty, string.Empty }); onIssueFound(issue); onComplete(); return; } var shaderGuids = AssetDatabase.FindAssets("t:shader"); foreach (var guid in shaderGuids) { var assetPath = AssetDatabase.GUIDToAssetPath(guid); var shader = AssetDatabase.LoadMainAssetAtPath(assetPath) as Shader; List <ShaderCompilerData> shaderCompilerDataContainer; s_ShaderCompilerData.TryGetValue(shader.name, out shaderCompilerDataContainer); if (shaderCompilerDataContainer != null) { var descriptor = new ProblemDescriptor ( id++, shader.name, Area.BuildSize, string.Empty, string.Empty ); foreach (var shaderCompilerData in shaderCompilerDataContainer) { var shaderKeywordSet = shaderCompilerData.shaderKeywordSet.GetShaderKeywords().ToArray(); #if UNITY_2019_3_OR_NEWER var keywords = shaderKeywordSet.Select(keyword => ShaderKeyword.IsKeywordLocal(keyword) ? ShaderKeyword.GetKeywordName(shader, keyword) : ShaderKeyword.GetGlobalKeywordName(keyword)).ToArray(); #else var keywords = shaderKeywordSet.Select(keyword => keyword.GetKeywordName()).ToArray(); #endif var keywordString = String.Join(", ", keywords); if (string.IsNullOrEmpty(keywordString)) { keywordString = "<no keywords>"; } var issue = new ProjectIssue(descriptor, shader.name, IssueCategory.Shaders, new Location(assetPath)); issue.SetCustomProperties(new[] { shaderCompilerData.shaderCompilerPlatform.ToString(), keywordString, }); onIssueFound(issue); } } } onComplete(); }
void AddShader(Shader shader, string assetPath, int id, Action <ProjectIssue> onIssueFound) { var variantCount = k_NotAvailable; #if UNITY_2018_2_OR_NEWER // add variants first if (s_ShaderVariantData != null) { if (s_ShaderVariantData.ContainsKey(shader)) { var variants = s_ShaderVariantData[shader]; variantCount = variants.Count.ToString(); AddVariants(shader, assetPath, id++, variants, onIssueFound); } else { variantCount = "0"; } } #endif var shaderName = shader.name; var shaderHasError = false; #if UNITY_2019_4_OR_NEWER shaderHasError = ShaderUtil.ShaderHasError(shader); #endif if (shaderHasError) { shaderName = Path.GetFileNameWithoutExtension(assetPath) + ": Parse Error"; var issueWithError = new ProjectIssue(k_ParseErrorDescriptor, shaderName, IssueCategory.Shaders, new Location(assetPath)); issueWithError.SetCustomProperties(new[] { k_NotAvailable, k_NotAvailable, k_NotAvailable, k_NotAvailable, k_NotAvailable, k_NotAvailable }); onIssueFound(issueWithError); return; } var descriptor = new ProblemDescriptor ( id++, shaderName, Area.BuildSize ); var passCount = k_NotAvailable; var keywordCount = k_NotAvailable; var hasInstancing = k_NotAvailable; /* * var usedBySceneOnly = false; * if (m_GetShaderVariantCountMethod != null) * { * var value = (ulong)m_GetShaderVariantCountMethod.Invoke(null, new object[] { shader, usedBySceneOnly}); * variantCount = value.ToString(); * } */ if (m_GetShaderGlobalKeywordsMethod != null && m_GetShaderLocalKeywordsMethod != null) { var globalKeywords = (string[])m_GetShaderGlobalKeywordsMethod.Invoke(null, new object[] { shader }); var localKeywords = (string[])m_GetShaderLocalKeywordsMethod.Invoke(null, new object[] { shader }); keywordCount = (globalKeywords.Length + localKeywords.Length).ToString(); } if (m_HasInstancingMethod != null) { var value = (bool)m_HasInstancingMethod.Invoke(null, new object[] { shader }); hasInstancing = value.ToString(); } // srp batcher var isSrpBatcherCompatible = false; if (m_GetShaderGlobalKeywordsMethod != null && m_GetShaderLocalKeywordsMethod != null) { #if UNITY_2019_1_OR_NEWER if (RenderPipelineManager.currentPipeline != null) { int subShader = (int)m_GetShaderActiveSubshaderIndex.Invoke(null, new object[] { shader }); int SRPErrCode = (int)m_GetSRPBatcherCompatibilityCode.Invoke(null, new object[] { shader, subShader }); isSrpBatcherCompatible = (0 == SRPErrCode); } #endif } #if UNITY_2019_1_OR_NEWER passCount = shader.passCount.ToString(); #endif var issue = new ProjectIssue(descriptor, shaderName, IssueCategory.Shaders, new Location(assetPath)); issue.SetCustomProperties(new[] { variantCount, passCount, keywordCount, shader.renderQueue.ToString(), hasInstancing, isSrpBatcherCompatible.ToString() }); onIssueFound(issue); }