private Dictionary <string, string> GetDefinedMacroses(IBuffer buffer, out bool isSurface) { isSurface = false; var lexer = CppLexer.Create(buffer); lexer.Start(); var definedMacroses = new Dictionary <string, string>(); var shaderTarget = HlslConstants.SHADER_TARGET_25; while (lexer.TokenType != null) { var tokenType = lexer.TokenType; if (tokenType is CppDirectiveTokenNodeType) { lexer.Advance(); var context = lexer.GetTokenText().TrimStart(); var(pragmaType, firstValue) = GetPragmaAndValue(context); if (pragmaType.Equals("surface")) { isSurface = true; } // based on https://docs.unity3d.com/Manual/SL-ShaderPrograms.html // We do not have any solution how we could handle multi_compile direcitves. It is complex task because // a lot of different files could be produces from multi_compile combination // Right now, we will consider first combination. if (!firstValue.IsEmpty() && (pragmaType.Equals("multi_compile") || pragmaType.Equals("multi_compile_local") || pragmaType.Equals("shader_feature_local") || pragmaType.Equals("shader_feature"))) { definedMacroses[firstValue] = "1"; } if (pragmaType.Equals("target")) { var versionFromTarget = int.TryParse(firstValue.Replace(".", ""), out var result) ? result : HlslConstants.SHADER_TARGET_35; shaderTarget = Math.Max(shaderTarget, versionFromTarget); } if (pragmaType.Equals("geometry")) { shaderTarget = Math.Max(shaderTarget, HlslConstants.SHADER_TARGET_40); } if (pragmaType.Equals("hull") || pragmaType.Equals("domain")) { shaderTarget = Math.Max(shaderTarget, HlslConstants.SHADER_TARGET_46); } // https://en.wikibooks.org/wiki/GLSL_Programming/Unity/Cookies if (pragmaType.Equals("multi_compile_lightpass")) { // multi_compile_lightpass == multi_compile DIRECTIONAL, DIRECTIONAL_COOKIE, POINT, POINT_NOATT, POINT_COOKIE, SPOT definedMacroses["DIRECTIONAL"] = "1"; } // TODO: handle built-in https://docs.unity3d.com/Manual/SL-MultipleProgramVariants.html // multi_compile_fwdbase, multi_compile_fwdadd, multi_compile_fwdadd_fullshadows, multi_compile_fog // could not find information about that directives } lexer.Advance(); } definedMacroses["SHADER_TARGET"] = shaderTarget.ToString(); return(definedMacroses); }
public IEnumerable <CppFileLocation> GetIncludes(CppFileLocation cppFileLocation) { // PSI is not commited here // TODO: cpp global cache should calculate cache only when PSI for file with cpp injects is committed. var sourceFile = cppFileLocation.GetRandomSourceFile(mySolution); var range = cppFileLocation.RootRange; Assertion.Assert(range.IsValid, "range.IsValid"); var buffer = sourceFile.Document.Buffer; var type = GetShaderProgramType(buffer, range.StartOffset); var includeType = GetIncludeProgramType(type); yield return(new CppFileLocation(myCppExternalModule, mySolution.SolutionDirectory.Combine(Utils.ShaderConfigFile))); if (includeType != InjectedHlslProgramType.Uknown) { var includes = GetIncludesLocation(sourceFile, includeType); foreach (var include in includes) { yield return(include); } } var cgIncludeFolder = CgIncludeDirectoryTracker.GetCgIncludeFolderPath(myUnityVersion); if (!cgIncludeFolder.ExistsDirectory) { yield break; } if (type == InjectedHlslProgramType.CGProgram) { var hlslSupport = cgIncludeFolder.Combine("HLSLSupport.cginc"); if (hlslSupport.ExistsFile) { yield return(new CppFileLocation(myCppExternalModule, hlslSupport)); } var variables = cgIncludeFolder.Combine("UnityShaderVariables.cginc"); if (variables.ExistsFile) { yield return(new CppFileLocation(myCppExternalModule, variables)); } } var lexer = CppLexer.Create(ProjectedBuffer.Create(buffer, range)); lexer.Start(); while (lexer.TokenType != null) { var tokenType = lexer.TokenType; if (tokenType is CppDirectiveTokenNodeType) { lexer.Advance(); var context = lexer.GetTokenText().TrimStart(); if (context.StartsWith("surface")) { var unityCG = cgIncludeFolder.Combine("UnityCG.cginc"); if (unityCG.ExistsFile) { yield return(new CppFileLocation(myCppExternalModule, unityCG)); } var lighting = cgIncludeFolder.Combine("Lighting.cginc"); if (lighting.ExistsFile) { yield return(new CppFileLocation(myCppExternalModule, lighting)); } var unityPbsLighting = cgIncludeFolder.Combine("UnityPBSLighting.cginc"); if (unityPbsLighting.ExistsFile) { yield return(new CppFileLocation(myCppExternalModule, unityPbsLighting)); } var autoLight = cgIncludeFolder.Combine("AutoLight.cginc"); if (autoLight.ExistsFile) { yield return(new CppFileLocation(myCppExternalModule, autoLight)); } break; } // TODO: optimization if we found vertex/fragment/geometry/hull/domain? } lexer.Advance(); } }