private static void ParseModifier(ShaderLanguage foundation, XmlNode modifierNode) { XmlAttribute attName = modifierNode.Attributes["name"]; if (attName == null) { return; } Modifier modifier = new Modifier(); modifier.NativeText = attName.InnerText; foreach (XmlNode child in modifierNode) { if (child.Name.ToLower() != "requirement") { continue; } XmlAttribute attCSharp = child.Attributes["csharp"]; if (attCSharp != null && !string.IsNullOrWhiteSpace(attCSharp.InnerText)) { modifier.Requirements.Add(attCSharp.InnerText.ToLower()); } } if (modifier.Requirements.Count > 0 && !string.IsNullOrWhiteSpace(modifier.NativeText)) { foundation._modifiers.Add(modifier); } }
internal void Initialize(TranslationRunner runner, ShaderLanguage language, List <string> preprocessorSymbols, TranslationFlags flags) { Flags = flags; Runner = runner; Language = language; ParseOptions = new CSharpParseOptions(LanguageVersion.CSharp7_3, DocumentationMode.Parse, SourceCodeKind.Regular, preprocessorSymbols); }
internal void Clear() { SourceSegment seg = _lastSegment; SourceSegment prev = null; while (seg != null) { prev = seg.Previous; Pooling.SourceSegments.Put(seg); seg = prev; } _firstSegment = null; _lastSegment = null; _curSegment = null; foreach (ScopeInfo si in _scopes) { Pooling.Scopes.Put(si); } Pooling.Scopes.Put(_currentScope); _rootScope = null; _currentScope = null; _language = null; }
private static void ParseWord(ShaderLanguage foundation, XmlNode wordNode) { Type translatedType = ShaderType.RetrieveType(wordNode.Attributes["type"].InnerText); if (translatedType == null) { return; } bool uniformDimensionSingular = false; if (wordNode.Attributes["uniformSizeIsSingular"] != null) { bool.TryParse(wordNode.Attributes["uniformSizeIsSingular"].InnerText, out uniformDimensionSingular); } if (translatedType.IsGenericType) { foreach (XmlNode subTypeNode in wordNode) { if (subTypeNode.Name.ToLower() != "generic") { continue; } string generic = subTypeNode.Attributes["type"]?.InnerText; string nativeName = subTypeNode.Attributes["name"]?.InnerText; if (!string.IsNullOrWhiteSpace(generic) && !string.IsNullOrWhiteSpace(nativeName)) { Type genericType = ShaderType.RetrieveType(generic) ?? throw new TypeAccessException($"The type {generic} is not valid in {foundation.Language} lexicon."); Type finalType = translatedType.MakeGenericType(genericType); foundation._keywords.Add(finalType, new Translation() { NativeText = nativeName, UniformSizeIsSingular = uniformDimensionSingular, }); } } } else { string generic = wordNode.Attributes["type"]?.InnerText; string nativeName = wordNode.Attributes["name"]?.InnerText; if (!string.IsNullOrWhiteSpace(generic) && !string.IsNullOrWhiteSpace(nativeName)) { foundation._keywords.Add(translatedType, new Translation() { NativeText = nativeName, UniformSizeIsSingular = uniformDimensionSingular, }); } } }
/// <summary> /// Creates a new instance of <see cref="ShaderType"/>. /// </summary> /// <param name="translation">The language-specific translation of the original type.</param> /// <param name="originalType">The original type.</param> /// <param name="lang">The shader language which the type belongs to.</param> internal ShaderType(ShaderLanguage lang, string translation, Type originalType) { IsRegisteredType = TypeHelper.IsRegisteredType(originalType); IsUnorderedAccessType = TypeHelper.IsUnorderedAccessType(originalType); _dimensions = new List <int>(); Dimensions = _dimensions.AsReadOnly(); Language = lang; OriginalType = originalType; Translation = translation; ElementType = originalType.IsArray ? originalType.GetElementType() : originalType; WasArrayType = originalType.IsArray; if (ElementType.IsValueType) { if (typeof(IVector).IsAssignableFrom(ElementType)) { IsVector = true; int elementCount = (int)ElementType.GetField("ELEMENT_COUNT").GetValue(null); SubElementSizeOf = (int)ElementType.GetField("ELEMENT_SIZE").GetValue(null); SizeOf = (int)ElementType.GetField("SIZE_OF").GetValue(null); Type eType = (Type)ElementType.GetField("ElementType").GetValue(null); _dataTypes.TryGetValue(eType, out _dataType); _dimensions.Add(elementCount); } else if (typeof(IMatrix).IsAssignableFrom(ElementType)) { IsMatrix = true; int rowCount = (int)ElementType.GetField("ROW_COUNT").GetValue(null); int colCount = (int)ElementType.GetField("COLUMN_COUNT").GetValue(null); SubElementSizeOf = (int)ElementType.GetField("ELEMENT_SIZE").GetValue(null); SizeOf = (int)ElementType.GetField("SIZE_OF").GetValue(null); Type eType = (Type)ElementType.GetField("ElementType").GetValue(null); _dataTypes.TryGetValue(eType, out _dataType); _dimensions.Add(rowCount); _dimensions.Add(colCount); } else { SubElementSizeOf = Marshal.SizeOf(ElementType); SizeOf = SubElementSizeOf; _dataTypes.TryGetValue(ElementType, out _dataType); _dimensions.Add(1); } } SubElementCount = GetTotalElements(); }
internal void Initialize(ShaderTranslationContext sc, TranslationFlags flags) { _flags = flags; _language = sc.Language; _currentScope = Pooling.Scopes.Get(); _currentScope.Type = ScopeType.Class; _currentScope.TypeInfo = new ShaderType(_language, sc.ShaderType.Name, sc.ShaderType); _currentScope.Namespace = $"{sc.ShaderType.Namespace}.{sc.ShaderType.Name}"; _rootScope = _currentScope; _firstSegment = Pooling.SourceSegments.Get(); _firstSegment.Value = ""; _curSegment = _firstSegment; _lastSegment = _curSegment; }
internal TranslationRunner() { _processors = new Dictionary <Type, NodeProcessor>(); ShaderLanguage.LoadEmbedded <HlslLanguage>("SharpShader.Languages.HLSL.lang.xml"); ShaderLanguage.LoadEmbedded <GlslFoundation>("SharpShader.Languages.GLSL.lang.xml"); // Preprocessors IEnumerable <Type> types = ShaderType.FindOfType <NodeProcessor>(); foreach (Type t in types) { NodeProcessor pp = Activator.CreateInstance(t) as NodeProcessor; _processors.Add(pp.ParsedType, pp); } }
internal static void LoadEmbedded <T>(string embeddedName) where T : ShaderLanguage { using (Stream stream = EmbeddedResource.GetStream(embeddedName)) { XmlDocument doc = new XmlDocument(); doc.Load(stream); foreach (XmlNode rootNode in doc) { if (rootNode.Name.ToLower() != "lexicon") { continue; } XmlAttribute attLanguage = rootNode.Attributes["language"]; if (attLanguage != null && Enum.TryParse(attLanguage.InnerText, out OutputLanguage language)) { ShaderLanguage foundation = Activator.CreateInstance(typeof(T), BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new object[] { language }, null) as ShaderLanguage; foreach (XmlNode node in rootNode) { switch (node.Name.ToLower()) { case "word": ParseWord(foundation, node); break; case "modifier": ParseModifier(foundation, node); break; } } _foundations.Add(language, foundation); } else { throw new XmlException("The specified shader language is invalid or missing."); } } } }
internal TranslationContext Run(TranslationArgs args) { List <string> preprocessorSymbols = null; if (args.PreprocessorSymbols != null) { preprocessorSymbols = new List <string>(args.PreprocessorSymbols); } Stopwatch mainTimer = new Stopwatch(); mainTimer.Start(); ShaderLanguage foundation = ShaderLanguage.Get(args.Language); TranslationContext context = Pooling.Contexts.Get(); context.Initialize(this, foundation, preprocessorSymbols, args.Flags); Message("Analyzing", TranslationMessageType.Status); AnalysisInfo analysis = Analyze(context, args.CSharpSources); Message($"Analysis completed"); if (analysis.HasError) { foreach (TranslationMessage msg in context.Messages) { Message(msg.Text, msg.MessageType); } Message($"Cannot proceed until errors are fixed. Aborting."); } else { Message($"Mapping shader classes", TranslationMessageType.Status); Map(context, analysis.Trees); Message($"Mapping completed. Found {context.Shaders.Count} shader classes."); foreach (ShaderTranslationContext sc in context.Shaders) { Message($"Translating {sc.Name}", TranslationMessageType.Status); Stopwatch timer = new Stopwatch(); timer.Start(); Message($"Translating to {context.Language.Language}"); Translate(sc, sc.RootNode); sc.FinalSource = sc.Source.ToString(); timer.Stop(); Message($" Finished '{sc.Name}' in {timer.Elapsed.TotalMilliseconds:N2} milliseconds"); } mainTimer.Stop(); foreach (TranslationMessage msg in context.Messages) { Message(msg.Text, msg.MessageType); } int errors = context.Messages.Count(t => t.MessageType == TranslationMessageType.Error); int warnings = context.Messages.Count(t => t.MessageType == TranslationMessageType.Warning); Message($"Finished conversion of { args.CSharpSources.Count} source(s) with {errors} errors and {warnings} warnings. "); Message($"Took {mainTimer.Elapsed.TotalMilliseconds:N2} milliseconds"); } return(context); }