public CompileData(string shaderCode, string shaderType, OnCompilationFinished compilationFinished, string documentDir) { ShaderCode = shaderCode; ShaderType = shaderType; CompilationFinished = compilationFinished; DocumentDir = documentDir; }
internal void RequestCompile(string shaderCode, string sShaderType, OnCompilationFinished compilationFinishedHandler, string documentDir) { StartGlThreadOnce(); while (compileRequests.TryTake(out _)) { ; //remove pending compiles } var data = new CompileData(shaderCode, sShaderType, compilationFinishedHandler, documentDir); compileRequests.TryAdd(data); //put compile on request list }
internal void RequestCompile(string shaderCode, string sShaderType, OnCompilationFinished compilationFinishedHandler, string documentDir) { StartGlThreadOnce(); //conversion if (!mappingContentTypeToShaderType.TryGetValue(sShaderType, out ShaderType shaderType)) { shaderType = ShaderType.FragmentShader; } while (compileRequests.TryTake(out CompileData dataOld)) { ; //remove pending compiles } var data = new CompileData { ShaderCode = shaderCode, ShaderType = shaderType, DocumentDir = documentDir, CompilationFinished = compilationFinishedHandler }; compileRequests.TryAdd(data); //put compile on request list }
// Returns true when compilation is finished due to one of these reasons // * Was stopped (CompilationTask.Stopped will be true) // * Compilation had errors (CompilationTask.CompileErrors will be true) // * Compilation succesfully completed without errors. public bool Poll() { HandleOnCompilationTaskStarted(); if (Stopped) { HandleOnCompilationTaskFinished(); return(true); } Dictionary <ScriptAssembly, ScriptCompilerBase> finishedCompilerTasks = null; // Check if any compiler processes are finished. foreach (var task in compilerTasks) { var compiler = task.Value; // Did compiler task finish? if (compiler.Poll()) { if (finishedCompilerTasks == null) { finishedCompilerTasks = new Dictionary <ScriptAssembly, ScriptCompilerBase>(); } var assembly = task.Key; finishedCompilerTasks.Add(assembly, compiler); } } // Save compiler messages from finished compiler processes and check for compile errors. if (finishedCompilerTasks != null) { foreach (var task in finishedCompilerTasks) { var assembly = task.Key; var compiler = task.Value; var messages = compiler.GetCompilerMessages(); var messagesList = messages.ToList(); compiledAssemblies.Add(assembly, messagesList.ToArray()); if (RunPostProcessors && !messagesList.Any(m => m.type == CompilerMessageType.Error)) { var sourcePath = AssetPath.Combine(buildOutputDirectory, assembly.Filename); try { File.Copy(sourcePath, assembly.FullPath, true); var postProcessorTask = new PostProcessorTask(assembly, messagesList, buildOutputDirectory, postProcessFunc); postProcessorTask.Poll(); OnPostProcessingStarted?.Invoke(assembly); postProcessorTasks.Add(postProcessorTask); } catch (IOException e) { UnityEngine.Debug.LogError($"Fail to copy {sourcePath} to {assembly.FullPath} before post processing the assembly. Skipping post processing.\n{e}"); // OnCompilationFinished callbacks might add more compiler messages OnCompilationFinished?.Invoke(assembly, messagesList); processedAssemblies.Add(assembly, messagesList.ToArray()); } } else { // OnCompilationFinished callbacks might add more compiler messages OnCompilationFinished?.Invoke(assembly, messagesList); processedAssemblies.Add(assembly, messagesList.ToArray()); } if (!CompileErrors) { CompileErrors = messagesList.Any(m => m.type == CompilerMessageType.Error); } compilerTasks.Remove(assembly); compiler.Dispose(); } } HashSet <PostProcessorTask> finishedPostProcessorTasks = null; foreach (var postProcessorTask in postProcessorTasks) { // We break out of this loop instead to continuing to ensure that // OnCompilationFinished events are emitted in the same order as // they finished compiling. if (!postProcessorTask.Poll()) { break; } // Do not copy the post processed assembly in OnCompilationFinished // if any of the running compilers have a reference to the assembly. // As we might copy it while the compiler has the assembly open. if (AnyRunningCompilerHasReference(postProcessorTask.Assembly)) { break; } var messagesList = postProcessorTask.CompilerMessages; // OnCompilationFinished callbacks might add more compiler messages OnCompilationFinished?.Invoke(postProcessorTask.Assembly, messagesList); processedAssemblies.Add(postProcessorTask.Assembly, messagesList.ToArray()); if (!CompileErrors) { CompileErrors = messagesList.Any(m => m.type == CompilerMessageType.Error); } if (finishedPostProcessorTasks == null) { finishedPostProcessorTasks = new HashSet <PostProcessorTask>(); } finishedPostProcessorTasks.Add(postProcessorTask); } if (finishedPostProcessorTasks != null) { foreach (var finishedPostProcessorTask in finishedPostProcessorTasks) { postProcessorTasks.Remove(finishedPostProcessorTask); } } // If StopOnFirstError is set, do not queue assemblies for compilation in case of compile errors. bool stopOnFirstError = (compilationTaskOptions & CompilationTaskOptions.StopOnFirstError) == CompilationTaskOptions.StopOnFirstError; if (stopOnFirstError && CompileErrors) { pendingAssemblies.Clear(); if (FinishedCompilation) { HandleOnCompilationTaskFinished(); } return(FinishedCompilation); } // Queue pending assemblies for compilation if we have no running compilers or if compilers have finished. if (compilerTasks.Count == 0 || (finishedCompilerTasks != null && finishedCompilerTasks.Count > 0)) { QueuePendingAssemblies(); } if (FinishedCompilation) { HandleOnCompilationTaskFinished(); } return(FinishedCompilation); }
void PollPostProcessors() { if (pendingPostProcessorTasks.Count == 0 && postProcessorTasks.Count == 0) { return; } // Not all codegen assemblies have been compiled yet. if (!AreAllCodegenAssembliesCompiled) { // If any codegen assemblies are not getting compiled, clear // pending il post processing tasks. if (notCompiledCodeGenAssemblies.Any()) { pendingPostProcessorTasks.Clear(); } return; } List <PostProcessorTask> startedPostProcessorTasks = null; // Check if any pending post processors can be run foreach (var postProcessorTask in pendingPostProcessorTasks) { if (RunningMaxConcurrentProcesses) { break; } var assembly = postProcessorTask.Assembly; // We break out of this loop instead to continuing to ensure that // OnCompilationFinished events are emitted in the same order as // they finished compiling. if (IsAnyProcessUsingAssembly(assembly)) { break; } if (startedPostProcessorTasks == null) { startedPostProcessorTasks = new List <PostProcessorTask>(); } startedPostProcessorTasks.Add(postProcessorTask); postProcessorTask.Start(); LogStartInfo($"# Starting IL post processing on {assembly.Filename}", postProcessorTask.GetProcessStartInfo()); OnPostProcessingStarted?.Invoke(assembly); postProcessorTasks.Add(postProcessorTask); } if (startedPostProcessorTasks != null) { foreach (var postProcessorTask in startedPostProcessorTasks) { pendingPostProcessorTasks.Remove(postProcessorTask); } } HashSet <PostProcessorTask> finishedPostProcessorTasks = null; foreach (var postProcessorTask in postProcessorTasks) { // We break out of this loop instead to continuing to ensure that // OnCompilationFinished events are emitted in the same order as // they finished compiling. if (!postProcessorTask.Poll()) { break; } // Do not copy the post processed assembly in OnCompilationFinished // if any of the running compilers have a reference to the assembly. // As we might copy it while the compiler has the assembly open. if (IsAnyProcessUsingAssembly(postProcessorTask.Assembly)) { break; } var messagesList = postProcessorTask.GetCompilerMessages(); // OnCompilationFinished callbacks might add more compiler messages OnCompilationFinished?.Invoke(postProcessorTask.Assembly, messagesList); processedAssemblies.Add(postProcessorTask.Assembly, messagesList.ToArray()); if (!CompileErrors) { CompileErrors = messagesList.Any(m => m.type == CompilerMessageType.Error); } if (finishedPostProcessorTasks == null) { finishedPostProcessorTasks = new HashSet <PostProcessorTask>(); } finishedPostProcessorTasks.Add(postProcessorTask); } if (finishedPostProcessorTasks != null) { foreach (var finishedPostProcessorTask in finishedPostProcessorTasks) { finishedPostProcessorTask.Dispose(); postProcessorTasks.Remove(finishedPostProcessorTask); } } }
// Returns true when compilation is finished due to one of these reasons // * Was stopped (CompilationTask.Stopped will be true) // * Compilation had errors (CompilationTask.CompileErrors will be true) // * Compilation succesfully completed without errors. public bool Poll() { HandleOnCompilationTaskStarted(); if (Stopped) { HandleOnCompilationTaskFinished(); return(true); } Dictionary <ScriptAssembly, ScriptCompilerBase> finishedCompilerTasks = null; // Check if any compiler processes are finished. foreach (var task in compilerTasks) { var compiler = task.Value; // Did compiler task finish? if (compiler.Poll()) { if (finishedCompilerTasks == null) { finishedCompilerTasks = new Dictionary <ScriptAssembly, ScriptCompilerBase>(); } var assembly = task.Key; finishedCompilerTasks.Add(assembly, compiler); } } // Save compiler messages from finished compiler processes and check for compile errors. if (finishedCompilerTasks != null) { foreach (var task in finishedCompilerTasks) { var assembly = task.Key; var compiler = task.Value; var messages = compiler.GetCompilerMessages(); var messagesList = messages.ToList(); compiledAssemblies.Add(assembly, messagesList.ToArray()); bool havePostProcessors = ilPostProcessing != null && ilPostProcessing.HasPostProcessors; bool isCodeGenAssembly = codeGenAssemblies.Contains(assembly); bool hasCompileErrors = messagesList.Any(m => m.type == CompilerMessageType.Error); if (isCodeGenAssembly) { if (hasCompileErrors) { notCompiledCodeGenAssemblies.Add(assembly); } else { compiledCodeGenAssemblies.Add(assembly); } } if (havePostProcessors && notCompiledCodeGenAssemblies.Count == 0 && !hasCompileErrors && !isCodeGenAssembly) { var assemblySourcePath = AssetPath.Combine(buildOutputDirectory, assembly.Filename); var pdbSourcePath = AssetPath.Combine(buildOutputDirectory, assembly.PdbFilename); try { if (assemblySourcePath != assembly.FullPath) { File.Copy(assemblySourcePath, assembly.FullPath, true); } if (pdbSourcePath != assembly.PdbFullPath) { File.Copy(pdbSourcePath, assembly.PdbFullPath, true); } var postProcessorTask = new PostProcessorTask(assembly, messagesList, buildOutputDirectory, ilPostProcessing); pendingPostProcessorTasks.Add(postProcessorTask); } catch (IOException e) { UnityEngine.Debug.LogError($"Fail to copy {assemblySourcePath} or {pdbSourcePath} to {AssetPath.GetDirectoryName(assembly.FullPath)} before post processing the assembly. Skipping post processing.\n{e}"); // OnCompilationFinished callbacks might add more compiler messages OnCompilationFinished?.Invoke(assembly, messagesList); processedAssemblies.Add(assembly, messagesList.ToArray()); } } else { // OnCompilationFinished callbacks might add more compiler messages OnCompilationFinished?.Invoke(assembly, messagesList); processedAssemblies.Add(assembly, messagesList.ToArray()); } if (!CompileErrors) { CompileErrors = messagesList.Any(m => m.type == CompilerMessageType.Error); } // If a codgen / IL Post processor has compile errors, clear // pending assemblies waiting for compilation and assemblies // waiting to get post processed. if (isCodeGenAssembly && hasCompileErrors) { pendingPostProcessorTasks.Clear(); pendingAssemblies.Clear(); } compilerTasks.Remove(assembly); compiler.Dispose(); } } if (ilPostProcessing != null && ilPostProcessing.HasPostProcessors) { PollPostProcessors(); } // If StopOnFirstError is set, do not queue assemblies for compilation in case of compile errors. bool stopOnFirstError = (compilationTaskOptions & CompilationTaskOptions.StopOnFirstError) == CompilationTaskOptions.StopOnFirstError; if (stopOnFirstError && CompileErrors) { foreach (var pendingAssembly in pendingAssemblies) { if (UnityCodeGenHelpers.IsCodeGen(pendingAssembly.Filename)) { notCompiledCodeGenAssemblies.Add(pendingAssembly); } } pendingAssemblies.Clear(); if (FinishedCompilation) { HandleOnCompilationTaskFinished(); } return(FinishedCompilation); } // Queue pending assemblies for compilation if we have no running compilers or if compilers have finished. if (compilerTasks.Count == 0 || (finishedCompilerTasks != null && finishedCompilerTasks.Count > 0)) { QueuePendingAssemblies(); } if (FinishedCompilation) { HandleOnCompilationTaskFinished(); } return(FinishedCompilation); }