public static ShaderParsedCombinations ParseShaderCombinations(Shader shader, bool usedBySceneOnly, bool withLog = true) { if (shader == null || !ShaderUtils.HasCodeSnippets(shader)) { return(null); } var assetPath = AssetDatabase.GetAssetPath(shader); var deps = AssetDatabase.GetDependencies(assetPath); long lastWriteTime = 0; for (int i = 0; i < deps.Length; ++i) { var fi = new FileInfo(deps[i]); if (fi.Exists) { if (fi.LastWriteTime.ToFileTime() > lastWriteTime) { lastWriteTime = fi.LastWriteTime.ToFileTime(); } } } ShaderParsedCombinationsItem item; if (s_ShaderParsedCombinationsCache.TryGetValue(shader, out item)) { if (item.lastWriteTime != lastWriteTime) { s_ShaderParsedCombinationsCache.Remove(shader); } else { return(item.data); } } ShaderParsedCombinations result = null; try { var fixedShaderName = shader.name.Replace('/', '-'); var combFilePath = String.Format("{0}/ParsedCombinations-{1}.shader", GetProjectUnityTempPath(), fixedShaderName); if (File.Exists(combFilePath)) { File.Delete(combFilePath); } Func <String, String[]> keywordsSpliter = src => { var srcKeywords = src.Split(' '); var dstKeywords = new List <String>(); for (int j = 0; j < srcKeywords.Length; ++j) { var x = srcKeywords[j].Trim(); if (!String.IsNullOrEmpty(x) && !dstKeywords.Contains(x)) { dstKeywords.Add(x); } } if (dstKeywords.Count > 0) { return(dstKeywords.ToArray()); } return(null); }; ShaderUtils.OpenShaderCombinations(shader, true, withLog); if (File.Exists(combFilePath)) { var lines = File.ReadAllLines(combFilePath); ShaderParsedCombinations.Snippet curSnippet = null; for (int i = 0; i < lines.Length; ++i) { var line = lines[i]; if (String.IsNullOrEmpty(line) || Char.IsWhiteSpace(line[0])) { continue; } Match match = ShaderParsedCombinations.REG_FILE_HEADER.Match(line); if (match.Success) { if (match.Groups.Count > 1) { int num; if (int.TryParse(match.Groups[1].Value, out num) && num > 0) { result = new ShaderParsedCombinations(); result.shader = shader; result.snippets = new List <ShaderParsedCombinations.Snippet>(num); } } } else if (result != null && (match = ShaderParsedCombinations.REG_SNIPPET_ID.Match(line)).Success) { if (match.Groups.Count > 2) { int id; if (int.TryParse(match.Groups[1].Value, out id)) { int bits; if (int.TryParse(match.Groups[2].Value, System.Globalization.NumberStyles.HexNumber, null, out bits)) { var snippet = new ShaderParsedCombinations.Snippet(); curSnippet = snippet; snippet.id = id; snippet.platformBits = bits; result.snippets.Add(snippet); } } } } else if (curSnippet != null && (match = ShaderParsedCombinations.REG_SHADER_FEATURE_KEYWORDS.Match(line)).Success) { if (match.Groups.Count > 1) { var keywords = keywordsSpliter(match.Groups[1].Value); if (keywords != null) { curSnippet.shader_features = keywords; } } } else if (curSnippet != null && (match = ShaderParsedCombinations.REG_MULTI_COMPILE_KEYWORDS.Match(line)).Success) { if (match.Groups.Count > 1) { var keywords = keywordsSpliter(match.Groups[1].Value); if (keywords != null) { curSnippet.multi_compiles = keywords; } } } else if (curSnippet != null && (match = ShaderParsedCombinations.REG_BUILTIN_KEYWORDS.Match(line)).Success) { if (match.Groups.Count > 1) { var keywords = keywordsSpliter(match.Groups[1].Value); if (keywords != null) { curSnippet.builtins = keywords; } } } else if (curSnippet != null && (match = ShaderParsedCombinations.REG_VARIANTS_NUM.Match(line)).Success) { if (match.Groups.Count > 1) { int num; if (int.TryParse(match.Groups[1].Value, out num) && num > 0) { curSnippet.variants = new List <String[]>(num); } } } else if (curSnippet != null && line.StartsWith(ShaderParsedCombinations.TAG_NO_KEYWORDS_DEFINED)) { if (curSnippet.variants != null) { curSnippet.variants = null; } } else if (curSnippet != null && curSnippet.variants != null) { var keywords = keywordsSpliter(line); if (keywords != null) { curSnippet.variants.Add(keywords); } } } } } catch (Exception e) { Debug.LogException(e); } s_ShaderParsedCombinationsCache.Add(shader, new ShaderParsedCombinationsItem { data = result, lastWriteTime = lastWriteTime }); return(result); }
public String Dump() { String result; var sb = new StringBuilder(); sb.Append(ShaderUtils.DumpShaderPasses(shader)); if (snippets != null && snippets.Count > 0) { sb.AppendFormat("// Total snippets: {0}", snippets.Count).AppendLine(); sb.AppendLine(); for (int i = 0; i < snippets.Count; ++i) { var snippet = snippets[i]; sb.AppendFormat("// Snippet #{0} platforms {1:x}:", snippet.id, snippet.platformBits).AppendLine(); sb.AppendLine(); if (snippet.shader_features != null && snippet.shader_features.Length > 0) { sb.AppendFormat("Keywords stripped away when not used:\n\n{0}", String.Join("\n", snippet.shader_features)).AppendLine(); sb.AppendLine(); } if (snippet.multi_compiles != null && snippet.multi_compiles.Length > 0) { sb.AppendFormat("Keywords always included into build:\n\n{0}", String.Join("\n", snippet.multi_compiles)).AppendLine(); sb.AppendLine(); } if (snippet.builtins != null && snippet.builtins.Length > 0) { sb.AppendFormat("Builtin keywords used:\n\n{0}", String.Join("\n", snippet.builtins)).AppendLine(); sb.AppendLine(); } sb.AppendLine(); if (snippet.variants != null && snippet.variants.Count > 0) { sb.AppendFormat("{0} keyword variants used in scene:", snippet.variants.Count).AppendLine(); sb.AppendLine(); for (int j = 0; j < snippet.variants.Count; ++j) { sb.AppendFormat("[{0}]:", j).AppendLine(); sb.Append(String.Join("\n", snippet.variants[j].ToArray())); sb.AppendLine(); sb.AppendLine(); } } else { sb.Append(TAG_NO_KEYWORDS_DEFINED).AppendLine(); } sb.AppendLine(); } result = sb.ToString(); } else { result = "Empty ShaderParsedCombinations."; } Debug.Log(result); return(result); }