Beispiel #1
0
		void SymbolTable::EvalFunctionReferenceClosure()
		{
			for (auto & func : Functions)
			{
				List<String> funcList;
				EnumerableHashSet<String> funcSet;
				for (auto & ref : func.Value->ReferencedFunctions)
				{
					funcList.Add(ref);
					funcSet.Add(ref);
				}
				for (int i = 0; i < funcList.Count(); i++)
				{
					RefPtr<FunctionSymbol> funcSym;
					if (Functions.TryGetValue(funcList[i], funcSym))
					{
						for (auto rfunc : funcSym->ReferencedFunctions)
						{
							if (funcSet.Add(rfunc))
								funcList.Add(rfunc);
						}
					}
				}
				func.Value->ReferencedFunctions = _Move(funcSet);
			}
		}
Beispiel #2
0
		void ShaderIR::EliminateDeadCode()
		{
			// mark entry points
			auto MarkUsing = [&](String compName, String userWorld)
			{
				if (auto defs = DefinitionsByComponent.TryGetValue(compName))
				{
					if (auto def = defs->TryGetValue(userWorld))
						(*def)->IsEntryPoint = true;
					else
					{
						for (auto & world : Shader->Pipeline->WorldDependency[userWorld]())
						{
							if (auto def2 = defs->TryGetValue(world))
							{
								(*def2)->IsEntryPoint = true;
								break;
							}
						}
					}
				}
			};
			for (auto & impOp : Shader->Pipeline->SyntaxNode->ImportOperators)
				for (auto & ref : impOp->Usings)
					MarkUsing(ref.Content, impOp->DestWorld.Content);
			for (auto & w : Shader->Pipeline->SyntaxNode->Worlds)
				for (auto & ref : w->Usings)
					MarkUsing(ref.Content, w->Name.Content);
			for (auto & comp : Definitions)
				if (comp->Implementation->ExportWorlds.Contains(comp->World) ||
					Shader->Pipeline->IsAbstractWorld(comp->World) &&
					(comp->Implementation->SyntaxNode->LayoutAttributes.ContainsKey(L"Pinned") || Shader->Pipeline->Worlds[comp->World]().SyntaxNode->LayoutAttributes.ContainsKey(L"Pinned")))
				{
					comp->IsEntryPoint = true;
				}

			List<ComponentDefinitionIR*> workList;
			HashSet<ComponentDefinitionIR*> referencedDefs;
			for (auto & def : Definitions)
			{
				if (def->IsEntryPoint)
				{
					if (referencedDefs.Add(def.Ptr()))
						workList.Add(def.Ptr());
				}
			}
			for (int i = 0; i < workList.Count(); i++)
			{
				auto def = workList[i];
				for (auto & dep : def->Dependency)
				{
					if (referencedDefs.Add(dep))
						workList.Add(dep);
				}
			}
			List<RefPtr<ComponentDefinitionIR>> newDefinitions;
			for (auto & def : Definitions)
			{
				if (referencedDefs.Contains(def.Ptr()))
				{
					newDefinitions.Add(def);
					EnumerableHashSet<ComponentDefinitionIR*> newSet;
					for (auto & comp : def->Users)
						if (referencedDefs.Contains(comp))
						{
							newSet.Add(comp);
						}
					def->Users = newSet;
					newSet.Clear();
					for (auto & comp : def->Dependency)
						if (referencedDefs.Contains(comp))
						{
							newSet.Add(comp);
						}
					def->Dependency = newSet;
				}
			}
			Definitions = _Move(newDefinitions);
			for (auto & kv : DefinitionsByComponent)
			{
				for (auto & def : kv.Value)
					if (!referencedDefs.Contains(def.Value))
						kv.Value.Remove(def.Key);
			}
		}
Beispiel #3
0
			virtual void Compile(CompileResult & result, CompilationContext & context, List<CompileUnit> & units, const CompileOptions & options) override
			{
				RefPtr<ProgramSyntaxNode> programSyntaxNode = new ProgramSyntaxNode();
				for (auto & unit : units)
				{
					programSyntaxNode->Include(unit.SyntaxNode.Ptr());
				}

				SymbolTable & symTable = context.Symbols;
				auto & shaderClosures = context.ShaderClosures;
				
				RefPtr<SyntaxVisitor> visitor = CreateSemanticsVisitor(&symTable, result.GetErrorWriter());
				try
				{
					programSyntaxNode->Accept(visitor.Ptr());
					if (result.GetErrorCount() > 0)
						return;
					// if user specified a template shader symbol, instantiate the template now
					String symbolToCompile = options.SymbolToCompile;
					if (symbolToCompile.Length())
					{
						auto templateShaders = programSyntaxNode->GetMembersOfType<TemplateShaderSyntaxNode>();
						for (auto & ts : templateShaders)
							if (ts->Name.Content == symbolToCompile)
							{
								auto shader = InstantiateShaderTemplate(result.GetErrorWriter(), &symTable, ts.Ptr(), options.TemplateShaderArguments);
								if (shader)
								{
									programSyntaxNode->Members.Add(shader);
									symbolToCompile = shader->Name.Content;
									programSyntaxNode->Accept(visitor.Ptr());
								}
								break;
							}
					}
					visitor = nullptr;
					symTable.EvalFunctionReferenceClosure();
					if (result.GetErrorCount() > 0)
						return;

					for (auto & shader : symTable.ShaderDependenceOrder)
					{
						if (shader->IsAbstract)
							continue;
						if (!shaderClosures.ContainsKey(shader->SyntaxNode->Name.Content))
						{
							auto shaderClosure = CreateShaderClosure(result.GetErrorWriter(), &symTable, shader);
							FlattenShaderClosure(result.GetErrorWriter(), &symTable, shaderClosure.Ptr());
							shaderClosures.Add(shader->SyntaxNode->Name.Content, shaderClosure);
						}
					}
					
					ResolveAttributes(&symTable);

					if (result.GetErrorCount() > 0)
						return;
					CodeGenBackend * backend = nullptr;
					switch(options.Target)
					{
					case CodeGenTarget::SPIRV:
						backend = backends["spirv"]().Ptr();
						break;
					case CodeGenTarget::GLSL:
						backend = backends["glsl"]().Ptr();
						break;
					case CodeGenTarget::GLSL_Vulkan:
						backend = backends["glsl_vk"]().Ptr();
						break;
					case CodeGenTarget::GLSL_Vulkan_OneDesc:
						backend = backends["glsl_vk_onedesc"]().Ptr();
						break;
					case CodeGenTarget::HLSL:
						backend = backends["hlsl"]().Ptr();
						break;
					default:
						// TODO: emit an appropriate diagnostic
						return;
					}

					Schedule schedule;
					if (options.ScheduleSource != "")
					{
						schedule = Schedule::Parse(options.ScheduleSource, options.ScheduleFileName, result.GetErrorWriter());
					}
					for (auto shader : shaderClosures)
					{
						// generate shader variant from schedule file, and also apply mechanic deduction rules
						if (!shader.Value->IR)
							shader.Value->IR = GenerateShaderVariantIR(result, shader.Value.Ptr(), schedule, &symTable);
					}
					if (options.Mode == CompilerMode::ProduceShader)
					{
						if (result.GetErrorWriter()->GetErrorCount() > 0)
							return;
						// generate IL code
						
						RefPtr<ICodeGenerator> codeGen = CreateCodeGenerator(&symTable, result);
						if (context.Program)
						{
							result.Program->Functions = context.Program->Functions;
							result.Program->Shaders = context.Program->Shaders;
							result.Program->Structs = context.Program->Structs;
							result.Program->ConstantPool = context.Program->ConstantPool;
						}
						for (auto & s : programSyntaxNode->GetStructs())
							codeGen->ProcessStruct(s.Ptr());

						for (auto & func : programSyntaxNode->GetFunctions())
							codeGen->ProcessFunction(func.Ptr());
						for (auto & shader : shaderClosures)
						{
							InsertImplicitImportOperators(result.GetErrorWriter(), shader.Value->IR.Ptr());
						}
						if (result.GetErrorCount() > 0)
							return;
						for (auto & shader : shaderClosures)
						{
							codeGen->ProcessShader(shader.Value->IR.Ptr());
						}
						if (result.GetErrorCount() > 0)
							return;
						// emit target code
						EnumerableHashSet<String> symbolsToGen;
						for (auto & unit : units)
						{
							for (auto & shader : unit.SyntaxNode->GetShaders())
								if (!shader->IsModule)
									symbolsToGen.Add(shader->Name.Content);
							for (auto & func : unit.SyntaxNode->GetFunctions())
								symbolsToGen.Add(func->Name.Content);
						}
						auto IsSymbolToGen = [&](String & shaderName)
						{
							if (symbolsToGen.Contains(shaderName))
								return true;
							for (auto & symbol : symbolsToGen)
								if (shaderName.StartsWith(symbol))
									return true;
							return false;
						};
						for (auto & shader : result.Program->Shaders)
						{
							if ((symbolToCompile.Length() == 0 && IsSymbolToGen(shader->Name))
								|| EscapeCodeName(symbolToCompile) == shader->Name)
							{
								StringBuilder glslBuilder;
								Dictionary<String, String> targetCode;
								result.CompiledSource[shader->Name] = backend->GenerateShader(result, &symTable, shader.Ptr(), result.GetErrorWriter());
							}
						}
					}
					else if (options.Mode == CompilerMode::GenerateChoice)
					{
						for (auto shader : shaderClosures)
						{
							if (options.SymbolToCompile.Length() == 0 || shader.Value->Name == options.SymbolToCompile)
							{
								auto &worldOrder = shader.Value->Pipeline->GetWorldTopologyOrder();
								for (auto & comp : shader.Value->AllComponents)
								{
									ShaderChoice choice;
									if (comp.Value.Symbol->ChoiceNames.Count() == 0)
										continue;
									if (comp.Value.Symbol->IsRequire())
										continue;
									choice.ChoiceName = comp.Value.Symbol->ChoiceNames.First();
									for (auto & impl : comp.Value.Symbol->Implementations)
									{
										for (auto w : impl->Worlds)
											if (comp.Value.Symbol->Type->ConstrainedWorlds.Contains(w))
												choice.Options.Add(ShaderChoiceValue(w));
									}
									if (auto defs = shader.Value->IR->DefinitionsByComponent.TryGetValue(comp.Key))
									{
										int latestWorldOrder = -1;
										for (auto & def : *defs)
										{
											int order = worldOrder.IndexOf(def.Key);
											if (latestWorldOrder < order)
											{
												choice.DefaultValue = def.Key;
												latestWorldOrder = order;
											}
										}
									}
									result.Choices.Add(choice);
								}
							}
						}
					}
					else
					{
                        result.GetErrorWriter()->diagnose(CodePosition(), Diagnostics::unsupportedCompilerMode);
						return;
					}
					context.Program = result.Program;
				}
				catch (int)
				{
				}
				catch (...)
				{
					throw;
				}
				return;
			}