private Effect CreateEffect(string effectName, EffectBytecode bytecode, ShaderMixinParameters usedParameters) { Effect effect; lock (cachedEffects) { if (!cachedEffects.TryGetValue(bytecode, out effect)) { effect = new Effect(graphicsDeviceService.GraphicsDevice, bytecode, usedParameters) { Name = effectName }; cachedEffects.Add(bytecode, effect); #if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP foreach (var type in bytecode.HashSources.Keys) { // TODO: the "/path" is hardcoded, used in ImportStreamCommand and ShaderSourceManager. Find a place to share this correctly. using (var pathStream = Asset.OpenAsStream(EffectCompilerBase.GetStoragePathFromShaderType(type) + "/path")) using (var reader = new StreamReader(pathStream)) { var path = reader.ReadToEnd(); directoryWatcher.Track(path); } } #endif } } return(effect); }
public string GetPathOfXkslShader(string effectName) { using (var pathStream = FileProvider.OpenStream(EffectCompilerBase.GetStoragePathFromShaderType(effectName) + "/path", VirtualFileMode.Open, VirtualFileAccess.Read)) using (var reader = new StreamReader(pathStream)) { return(reader.ReadToEnd()); } }
private Effect CreateEffect(string effectName, EffectBytecodeCompilerResult effectBytecodeCompilerResult, CompilerResults compilerResult) { Effect effect; lock (cachedEffects) { if (!isInitialized) { throw new InvalidOperationException("EffectSystem has been disposed. This Effect compilation has been cancelled."); } var usedParameters = compilerResult.UsedParameters; if (effectBytecodeCompilerResult.CompilationLog.HasErrors) { // Unregister result (or should we keep it so that failure never change?) List <CompilerResults> effectCompilerResults; if (earlyCompilerCache.TryGetValue(effectName, out effectCompilerResults)) { effectCompilerResults.Remove(compilerResult); } } CheckResult(effectBytecodeCompilerResult.CompilationLog); var bytecode = effectBytecodeCompilerResult.Bytecode; if (bytecode == null) { throw new InvalidOperationException("EffectCompiler returned no shader and no compilation error."); } if (!cachedEffects.TryGetValue(bytecode, out effect)) { effect = new Effect(graphicsDeviceService.GraphicsDevice, bytecode, usedParameters) { Name = effectName }; cachedEffects.Add(bytecode, effect); #if SILICONSTUDIO_PLATFORM_WINDOWS_DESKTOP foreach (var type in bytecode.HashSources.Keys) { // TODO: the "/path" is hardcoded, used in ImportStreamCommand and ShaderSourceManager. Find a place to share this correctly. using (var pathStream = FileProvider.OpenStream(EffectCompilerBase.GetStoragePathFromShaderType(type) + "/path", VirtualFileMode.Open, VirtualFileAccess.Read)) using (var reader = new StreamReader(pathStream)) { var path = reader.ReadToEnd(); directoryWatcher.Track(path); } } #endif } } return(effect); }
public CompilerResults GetCompilerResults(string effectName, CompilerParameters compilerParameters) { if (effectName == null) { throw new ArgumentNullException("effectName"); } if (compilerParameters == null) { throw new ArgumentNullException("compilerParameters"); } // Setup compilation parameters compilerParameters.EffectParameters.Platform = GraphicsDevice.Platform; compilerParameters.EffectParameters.Profile = DeviceManager?.ShaderProfile ?? GraphicsDevice.Features.RequestedProfile; // Copy optimization/debug levels compilerParameters.EffectParameters.OptimizationLevel = effectCompilerParameters.OptimizationLevel; compilerParameters.EffectParameters.Debug = effectCompilerParameters.Debug; var source = GetShaderSource(effectName); var compiler = EffectSystem.Compiler; var compilerResults = compiler.Compile(source, compilerParameters); // Watch the source code files var effectBytecodeCompilerResult = compilerResults.Bytecode.WaitForResult(); if (effectBytecodeCompilerResult.CompilationLog.HasErrors) { foreach (var m in effectBytecodeCompilerResult.CompilationLog.Messages) { if (TryGetFilePath(m, out string path)) { directoryWatcher.Track(path); } } } else { var bytecode = effectBytecodeCompilerResult.Bytecode; foreach (var type in bytecode.HashSources.Keys) { // TODO: the "/path" is hardcoded, used in ImportStreamCommand and ShaderSourceManager. Find a place to share this correctly. using (var pathStream = FileProvider.OpenStream(EffectCompilerBase.GetStoragePathFromShaderType(type) + "/path", VirtualFileMode.Open, VirtualFileAccess.Read)) using (var reader = new StreamReader(pathStream)) { var path = reader.ReadToEnd(); directoryWatcher.Track(path); } } } return(compilerResults); }
public static string GetPathOfSdslShader(string effectName, IVirtualFileProvider fileProvider, IVirtualFileProvider dbFileProvider = null) { var path = EffectCompilerBase.GetStoragePathFromShaderType(effectName); if (fileProvider.TryGetFileLocation(path, out var filePath, out _, out _)) { if (File.Exists(filePath)) { return(filePath); } } var pathUrl = path + "/path"; if (fileProvider.FileExists(pathUrl)) { using (var pathStream = fileProvider.OpenStream(pathUrl, VirtualFileMode.Open, VirtualFileAccess.Read)) using (var reader = new StreamReader(pathStream)) { var dbPath = reader.ReadToEnd(); if (File.Exists(dbPath)) { return(dbPath); } } } if (dbFileProvider != null) { return(GetPathOfSdslShader(effectName, dbFileProvider)); } //find locally if (LocalShaderFilePaths.TryGetValue(effectName, out var fp)) { return(fp); } return(null); }
protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext) { var compiler = GetOrCreateEffectCompiler(context); // Get main effect name (before the first dot) var isSdfx = ShaderMixinManager.Contains(effectName); var source = isSdfx ? new ShaderMixinGeneratorSource(effectName) : (ShaderSource) new ShaderClassSource(effectName); int permutationCount; lock (PermutationCount) { PermutationCount.TryGetValue(effectName, out permutationCount); permutationCount++; PermutationCount[effectName] = permutationCount; } commandContext.Logger.Verbose($"Trying permutation #{permutationCount} for effect [{effectName}]: \n{compilerParameters.ToStringPermutationsDetailed()}"); var compilerResults = compiler.Compile(source, compilerParameters); // Copy logs and if there are errors, exit directly compilerResults.CopyTo(commandContext.Logger); if (compilerResults.HasErrors) { return(Task.FromResult(ResultStatus.Failed)); } // Wait for result an check compilation status var completedTask = compilerResults.Bytecode.WaitForResult(); completedTask.CompilationLog.CopyTo(commandContext.Logger); if (completedTask.CompilationLog.HasErrors) { return(Task.FromResult(ResultStatus.Failed)); } // Register all dependencies var allSources = new HashSet <string>( completedTask.Bytecode.HashSources.Select(keyPair => keyPair.Key)); foreach (var className in allSources) { commandContext.RegisterInputDependency(new ObjectUrl(UrlType.Content, EffectCompilerBase.GetStoragePathFromShaderType(className))); } // Generate sourcecode if configured if (compilerParameters.ContainsKey(EffectSourceCodeKeys.Enable)) { var outputDirectory = UPath.Combine(package.RootDirectory, baseUrl); var fieldName = compilerParameters.Get(EffectSourceCodeKeys.FieldName); if (fieldName.StartsWith("binary")) { fieldName = fieldName.Substring("binary".Length); if (char.IsUpper(fieldName[0])) { fieldName = char.ToLower(fieldName[0]) + fieldName.Substring(1); } } var outputClassFile = effectName + "." + fieldName + "." + compilerParameters.EffectParameters.Platform + "." + compilerParameters.EffectParameters.Profile + ".cs"; var fullOutputClassFile = Path.Combine(outputDirectory.ToWindowsPath(), outputClassFile); commandContext.Logger.Verbose($"Writing shader bytecode to .cs source [{fullOutputClassFile}]."); using (var stream = new FileStream(fullOutputClassFile, FileMode.Create, FileAccess.Write, FileShare.Write)) EffectByteCodeToSourceCodeWriter.Write(effectName, compilerParameters, compilerResults.Bytecode.WaitForResult().Bytecode, new StreamWriter(stream, System.Text.Encoding.UTF8)); } return(Task.FromResult(ResultStatus.Successful)); }
protected override Task <ResultStatus> DoCommandOverride(ICommandContext commandContext) { var compiler = GetOrCreateEffectCompiler(context); // Get main effect name (before the first dot) var isPdxfx = ShaderMixinManager.Contains(effectName); var source = isPdxfx ? new ShaderMixinGeneratorSource(effectName) : (ShaderSource) new ShaderClassSource(effectName); int permutationCount; lock (PermutationCount) { PermutationCount.TryGetValue(effectName, out permutationCount); permutationCount++; PermutationCount[effectName] = permutationCount; } commandContext.Logger.Info("Trying permutation #{0} for effect [{1}]: \n{2}", permutationCount, effectName, compilerParameters.ToStringDetailed()); var compilerResults = compiler.Compile(source, compilerParameters); // Copy logs and if there are errors, exit directlry compilerResults.CopyTo(commandContext.Logger); if (compilerResults.HasErrors) { return(Task.FromResult(ResultStatus.Failed)); } // Register all dependencies var allSources = new HashSet <string>(compilerResults.Bytecode.WaitForResult().Bytecode.HashSources.Select(keyPair => keyPair.Key)); foreach (var className in allSources) { commandContext.RegisterInputDependency(new ObjectUrl(UrlType.Internal, EffectCompilerBase.GetStoragePathFromShaderType(className))); } // Generate sourcecode if configured if (compilerParameters.ContainsKey(EffectSourceCodeKeys.Enable)) { var outputDirectory = UPath.Combine(context.Package.RootDirectory, baseUrl); var outputClassFile = effectName + ".bytecode." + compilerParameters.Platform + "." + compilerParameters.Profile + ".cs"; var fullOutputClassFile = Path.Combine(outputDirectory.ToWindowsPath(), outputClassFile); commandContext.Logger.Info("Writing shader bytecode to .cs source [{0}]", fullOutputClassFile); using (var stream = new FileStream(fullOutputClassFile, FileMode.Create, FileAccess.Write, FileShare.Write)) EffectByteCodeToSourceCodeWriter.Write(effectName, compilerParameters, compilerResults.Bytecode.WaitForResult().Bytecode, new StreamWriter(stream, System.Text.Encoding.UTF8)); } return(Task.FromResult(ResultStatus.Successful)); }