/// <summary> /// Gets all the graphicsBackends, ensuring they have the required features. /// </summary> /// <param name="requiredFeatures">The required features.</param> /// <param name="throwOnFail">if set to <c>true</c> throws an error if any of the <paramref name="graphicsBackends" /> /// do not have the <paramref name="requiredFeatures">required features</paramref>.</param> /// <param name="graphicsBackends">The graphics graphicsBackends.</param> /// <returns></returns> /// <exception cref="ShaderGen.Tests.Tools.RequiredToolFeatureMissingException"></exception> public static IReadOnlyList <ToolChain> Requires( ToolFeatures requiredFeatures, bool throwOnFail, IEnumerable <GraphicsBackend> graphicsBackends) { GraphicsBackend[] backends = (graphicsBackends ?? _toolChainsByGraphicsBackend.Keys).ToArray(); if (backends.Length < 1) { backends = _toolChainsByGraphicsBackend.Keys.ToArray(); } List <string> missingBackends = new List <string>(backends.Length); List <ToolChain> found = new List <ToolChain>(backends.Length); foreach (GraphicsBackend backend in backends) { ToolChain toolChain = Get(backend); if (toolChain == null) { missingBackends.Add($"{backend} backend does not have a tool chain"); continue; } if (!toolChain.Features.HasFlag(requiredFeatures)) { missingBackends.Add( $"{backend} tool chain does not have the required {~toolChain.Features & requiredFeatures} feature(s)"); continue; } found.Add(toolChain); } if (throwOnFail && missingBackends.Count > 0) { string last = missingBackends.LastOrDefault(); throw new RequiredToolFeatureMissingException( missingBackends.Count < 2 ? $"The {last}." : $"The {string.Join(", ", missingBackends.Take(missingBackends.Count - 1))} and {last}."); } found.TrimExcess(); return(found.AsReadOnly()); }
public static LanguageBackend[] GetAllBackends(Compilation compilation, ToolFeatures features = ToolFeatures.Transpilation) => ToolChain.Requires(features, false).Select(t => t.CreateBackend(compilation)) .ToArray();
/// <summary> /// Initializes a new instance of the <see cref="ToolChain" /> class. For now tool chains are single tools, but this /// could be easily extended to support multiple steps. /// </summary> /// <param name="graphicsBackend">The graphics backend.</param> /// <param name="backendType">Type of the backend.</param> /// <param name="createBackend">The function to create the backend.</param> /// <param name="compileFunction">The compile function.</param> /// <param name="createHeadless">The function to create a headless graphics device.</param> /// <param name="createWindowed">The create windowed.</param> /// <exception cref="ArgumentOutOfRangeException">backendType</exception> private ToolChain(GraphicsBackend graphicsBackend, Type backendType, Func <Compilation, LanguageBackend> createBackend, CompileDelegate compileFunction, Func <GraphicsDevice> createHeadless, Func <GraphicsDevice> createWindowed) { if (!backendType.IsSubclassOf(typeof(LanguageBackend))) { throw new ArgumentOutOfRangeException(nameof(backendType), $"{backendType.Name} is not a descendent of {nameof(LanguageBackend)}."); } BackendType = backendType; // Calculate name (strip 'Backend' if present). Name = backendType.Name; if (Name.EndsWith("Backend", StringComparison.InvariantCultureIgnoreCase)) { Name = Name.Substring(0, Name.Length - 7); } GraphicsBackend = graphicsBackend; ToolFeatures features = ToolFeatures.None; if (createBackend != null) { _createBackend = createBackend; features |= ToolFeatures.Transpilation; } if (compileFunction != null) { _compileFunction = compileFunction; features |= ToolFeatures.Compilation; } // Don't allow creation of graphics devices on CI Servers. bool onCiServer = Environment.GetEnvironmentVariable("CI")?.ToLowerInvariant() == "true"; if (!onCiServer && createHeadless != null && GraphicsDevice.IsBackendSupported(graphicsBackend)) { try { // Try to create a headless graphics device using (createHeadless()) { } _createHeadless = createHeadless; features |= ToolFeatures.HeadlessGraphicsDevice; } catch { } } // TODO For future expansion, will need to review signature of function. if (!onCiServer && createWindowed != null && GraphicsDevice.IsBackendSupported(graphicsBackend)) { try { // Try to create a headless graphics device using (createWindowed()) { } _createWindowed = createWindowed; features |= ToolFeatures.WindowedGraphicsDevice; } catch { } } Features = features; // Add to lookup dictionaries. _toolChainsByGraphicsBackend.Add(graphicsBackend, this); _toolChainsByBackendType.Add(backendType, this); }
/// <summary> /// Gets the first tool chain (if any) with all the specified features. /// </summary> /// <param name="features">The features.</param> /// <returns></returns> public static ToolChain Get(ToolFeatures features) => Requires(features, false).FirstOrDefault();
/// <summary> /// Gets all the graphicsBackends, ensuring they have the required features. /// </summary> /// <param name="requiredFeatures">The required features.</param> /// <param name="throwOnFail">if set to <c>true</c> throws an error if any of the <paramref name="graphicsBackends" /> /// do not have the <paramref name="requiredFeatures">required features</paramref>.</param> /// <param name="graphicsBackends">The graphicsBackends required (leave empty to get all).</param> /// <returns></returns> /// <exception cref="ShaderGen.Tests.Tools.RequiredToolFeatureMissingException"></exception> public static IReadOnlyList <ToolChain> Requires(ToolFeatures requiredFeatures, bool throwOnFail, params GraphicsBackend[] graphicsBackends) => Requires(requiredFeatures, throwOnFail, (IEnumerable <GraphicsBackend>)graphicsBackends);
/// <summary> /// Gets all the graphicsBackends, ensuring they have the required features. /// </summary> /// <param name="requiredFeatures">The required features.</param> /// <param name="graphicsBackends">The graphicsBackends required (leave empty to get all).</param> /// <returns></returns> /// <exception cref="ShaderGen.Tests.Tools.RequiredToolFeatureMissingException"></exception> public static IReadOnlyList <ToolChain> Requires(ToolFeatures requiredFeatures, IEnumerable <GraphicsBackend> graphicsBackends) => Requires(requiredFeatures, true, graphicsBackends);
/// <summary> /// Gets the graphicsBackends, ensuring it has the required features. /// </summary> /// <param name="requiredFeatures">The required features.</param> /// <param name="throwOnFail">if set to <c>true</c> throws an error if any of the <paramref name="graphicsBackends" /> /// do not have the <paramref name="requiredFeatures">required features</paramref>.</param> /// <param name="graphicsBackend">The graphics backend.</param> /// <returns></returns> /// <exception cref="ShaderGen.Tests.Tools.RequiredToolFeatureMissingException"></exception> public static ToolChain Require( ToolFeatures requiredFeatures, bool throwOnFail, GraphicsBackend graphicsBackend) => Requires(requiredFeatures, throwOnFail, graphicsBackend).SingleOrDefault();
/// <summary> /// Gets the graphicsBackends, ensuring it has the required features. /// </summary> /// <param name="requiredFeatures">The required features.</param> /// <param name="graphicsBackend">The graphics backend.</param> /// <returns></returns> /// <exception cref="ShaderGen.Tests.Tools.RequiredToolFeatureMissingException"></exception> public static ToolChain Require( ToolFeatures requiredFeatures, GraphicsBackend graphicsBackend) => Requires(requiredFeatures, true, graphicsBackend).SingleOrDefault();