List<String>& PipelineSymbol::GetWorldTopologyOrder() { if (WorldTopologyOrder.Count() != 0) return WorldTopologyOrder; List<String> rs; HashSet<String> rsSet; bool changed = true; while (changed) { changed = false; for (auto & w : WorldDependency) { if (!rsSet.Contains(w.Key)) { bool canAdd = true; for (auto & dw : w.Value) if (!rsSet.Contains(dw)) { canAdd = false; break; } if (canAdd) { rsSet.Add(w.Key); rs.Add(w.Key); changed = true; } } } } WorldTopologyOrder = _Move(rs); return WorldTopologyOrder; }
int32_t CountDistinct(MEM_POOL_PTR mem_pool, struct low_data_struct *cur_value, struct low_data_struct* new_value) { if (cur_value == NULL || new_value == NULL) { return -1; } if (cur_value->data == NULL) { cur_value->type = HI_TYPE_SET; cur_value->len = 0; Equals * equals = new (mem_pool_malloc(mem_pool, sizeof(LDEquals))) LDEquals(); HashCoding* hash = new (mem_pool_malloc(mem_pool, sizeof(LDHash))) LDHash(); cur_value->data = new (mem_pool_malloc(mem_pool, sizeof(HashSet))) HashSet(equals, hash, mem_pool); } HashSet* set = (HashSet*) cur_value->data; if (set->Contains(new_value)) { return MILE_RETURN_SUCCESS; } else if (new_value->type != HI_TYPE_NULL) { struct low_data_struct* ld = (struct low_data_struct*) mem_pool_malloc( mem_pool, sizeof(struct low_data_struct)); memset(ld, 0, sizeof(struct low_data_struct)); copy_low_data_struct(mem_pool, ld, new_value); set->Add(ld); cur_value->len++; } return MILE_RETURN_SUCCESS; }
List<ShaderLibFile> CompileShaderSource(Spire::Compiler::CompileResult & compileResult, const CoreLib::String & src, Spire::Compiler::CompileOptions & options) { Spire::Compiler::NamingCounter = 0; RefPtr<ShaderCompiler> compiler = CreateShaderCompiler(); List<CompileUnit> units; HashSet<String> processedUnits; List<String> unitsToInclude; unitsToInclude.Add(L""); processedUnits.Add(L""); auto predefUnit = compiler->Parse(compileResult, LibIncludeString, L"stdlib"); for (int i = 0; i < unitsToInclude.Count(); i++) { auto inputFileName = unitsToInclude[i]; try { String source = src; if (i > 0) source = File::ReadAllText(inputFileName); auto unit = compiler->Parse(compileResult, source, Path::GetFileName(inputFileName)); units.Add(unit); if (unit.SyntaxNode) { for (auto inc : unit.SyntaxNode->Usings) { String includeFile = Path::Combine(Path::GetDirectoryName(inputFileName), inc.Content); if (processedUnits.Add(includeFile)) { unitsToInclude.Add(includeFile); } } } } catch (IOException) { compileResult.GetErrorWriter()->Error(1, L"cannot open file '" + Path::GetFileName(inputFileName) + L"'.", CodePosition(0, 0, L"")); } } units.Add(predefUnit); return CompileUnits(compileResult, compiler.Ptr(), units, options); }
bool SymbolTable::SortShaders() { HashSet<ShaderSymbol*> shaderSet; ShaderDependenceOrder.Clear(); List<ShaderSymbol *> nextShaders, currentShaders; // sort shaders in dependency order for (auto & shader : Shaders) { if (shader.Value->DependentShaders.Count() == 0) { ShaderDependenceOrder.Add(shader.Value.Ptr()); shaderSet.Add(shader.Value.Ptr()); } else currentShaders.Add(shader.Value.Ptr()); } while (currentShaders.Count()) { nextShaders.Clear(); for (auto & shader : currentShaders) { bool pass = true; for (auto & dshader : shader->DependentShaders) if (!shaderSet.Contains(dshader)) { pass = false; break; } if (pass) { ShaderDependenceOrder.Add(shader); shaderSet.Add(shader); } else nextShaders.Add(shader); } currentShaders.SwapWith(nextShaders); } return (ShaderDependenceOrder.Count() == Shaders.Count()); }
List<ShaderComponentSymbol*> ShaderIR::GetComponentDependencyOrder() { List<ShaderComponentSymbol*> result, workList; HashSet<String> set; for (auto & comp : DefinitionsByComponent) { bool emptyDependency = true; for (auto & def : comp.Value) if (def.Value->Dependency.Count()) { emptyDependency = false; break; } if (emptyDependency) { workList.Add(Shader->AllComponents[comp.Key]()); } } for (int i = 0; i < workList.Count(); i++) { auto comp = workList[i]; if (!set.Contains(comp->UniqueName)) { bool insertable = true; for (auto & def : DefinitionsByComponent[comp->UniqueName]()) { for (auto & dep : def.Value->Dependency) if (!set.Contains(dep->Component->UniqueName)) { insertable = false; goto breakLoc; } } breakLoc:; if (insertable) { if (set.Add(comp->UniqueName)) { result.Add(comp); for (auto & def : DefinitionsByComponent[comp->UniqueName]()) for (auto & user : def.Value->Users) workList.Add(user->Component); } } } } return result; }
void ChoiceForm::Autotune(float timeBudget) { bool countOnly = false; ResetButton_Clicked(nullptr); referenceFrame = ReadFrameData(choiceControl->RenderFrame()); EnumerableDictionary<String, Spire::Compiler::ShaderChoiceValue> currentChoices; currentBestValue = 1e30f; currentBestChoices = currentChoices; HashSet<String> selectedChoices; for (auto & chk : choiceCheckBoxes) if (chk.Value->Checked) selectedChoices.Add(chk.Key); autotuningLog.Clear(); auto startTimePoint = PerformanceCounter::Start(); int count = AutotuneHelper(selectedChoices, currentChoices, timeBudget, countOnly); float time = PerformanceCounter::EndSeconds(startTimePoint); autotuningLog << L"time: " << time << EndLine; printf("variant count: %d\ntime: %f\n", count, time); File::WriteAllText(L"autotuneLog.txt", autotuningLog.ToString()); if (!countOnly) { existingChoices = currentBestChoices; disableChoiceChangeCapture = true; for (auto & choice : existingChoices) { auto cmb = choiceComboBoxes[choice.Key].GetValue(); int idxToSelect = 0; for (int i = 0; i < cmb->Items.Count(); i++) if (cmb->GetTextItem(i)->GetText() == choice.Value.ToString()) { idxToSelect = i; break; } cmb->SetSelectedIndex(idxToSelect); } disableChoiceChangeCapture = false; Recompile(); ShaderChanged(currentShaderName); } }
void addThread(Thread *pthread) { Mutex::Locker lock(&ThreadMutex); ThreadSet.Add(pthread); }
void DFA_Graph::Generate(NFA_Graph * nfa) { table = new RegexCharTable(); List<RegexCharSet * > charSets; for (int i=0; i<nfa->translations.Count(); i++) { if (nfa->translations[i]->CharSet && nfa->translations[i]->CharSet->Ranges.Count()) charSets.Add(nfa->translations[i]->CharSet.operator->()); } CharTableGenerator gen(table.operator ->()); int elements = gen.Generate(charSets); CharElements = gen.elements; List<DFA_Node *> L,D; startNode = new DFA_Node(elements); startNode->ID = 0; startNode->Nodes.Add(nfa->start); L.Add(startNode); nodes.Add(startNode); List<Word> charElem; do { DFA_Node * node = L.Last(); L.RemoveAt(L.Count()-1); charElem.Clear(); node->IsFinal = false; for (int i=0; i<node->Nodes.Count(); i++) { CombineCharElements(node->Nodes[i], charElem); if (node->Nodes[i]->IsFinal) node->IsFinal = true; } for (int i=0; i<charElem.Count(); i++) { DFA_Node * n = new DFA_Node(0); for (int j=0; j<node->Nodes.Count(); j++) { for (int k=0; k<node->Nodes[j]->Translations.Count(); k++) { NFA_Translation * trans = node->Nodes[j]->Translations[k]; if (trans->CharSet->Elements.Contains(charElem[i])) { if (!n->Nodes.Contains(node->Nodes[j]->Translations[k]->NodeDest)) n->Nodes.Add(node->Nodes[j]->Translations[k]->NodeDest); } } } int fid = -1; for (int j=0; j<nodes.Count(); j++) { if ((*nodes[j]) == *n) { fid = j; break; } } if (fid == -1) { n->Translations.SetSize(elements); for (int m=0; m<elements; m++) n->Translations[m] = 0; n->ID = nodes.Count(); L.Add(n); nodes.Add(n); fid = nodes.Count()-1; } else delete n; n = nodes[fid].operator ->(); node->Translations[charElem[i]] = n; } } while (L.Count()); // Set Terminal Identifiers HashSet<int> terminalIdentifiers; for (int i=0; i<nodes.Count(); i++) { terminalIdentifiers.Clear(); for (int j=0; j<nodes[i]->Nodes.Count(); j++) { if (nodes[i]->Nodes[j]->IsFinal && !terminalIdentifiers.Contains(nodes[i]->Nodes[j]->TerminalIdentifier)) { nodes[i]->IsFinal = true; terminalIdentifiers.Add(nodes[i]->Nodes[j]->TerminalIdentifier); nodes[i]->TerminalIdentifiers.Add(nodes[i]->Nodes[j]->TerminalIdentifier); } } nodes[i]->TerminalIdentifiers.Sort(); } }
void ShaderIR::ResolveComponentReference() { // build bidirectional dependency map of component definitions for (auto & comp : Definitions) { comp->Dependency.Clear(); comp->Users.Clear(); } for (auto & comp : Definitions) { List<ShaderComponentSymbol *> workList; for (auto & dep : comp->Implementation->DependentComponents) workList.Add(dep); HashSet<ShaderComponentSymbol*> proceseedDefCompss; for (int i = 0; i < workList.Count(); i++) { auto dep = workList[i]; if (!proceseedDefCompss.Add(dep)) continue; auto & depDefs = DefinitionsByComponent[dep->UniqueName](); // select the best overload according to import operator ordering, // prefer user-pinned definitions (as provided in the choice file) List<String> depWorlds; depWorlds.Add(comp->World); for (auto & w : Shader->Pipeline->WorldDependency[comp->World]()) depWorlds.Add(w); for (int pass = 0; pass < 2; pass++) { // in the first pass, examine the pinned definitions only // in the second pass, examine all the rest definitions for (auto & depWorld : depWorlds) { bool isPinned = false; for (auto existingDef : dep->Type->PinnedWorlds) if (existingDef.StartsWith(depWorld)) { isPinned = true; break; } if (pass == 0 && !isPinned || pass == 1 && isPinned) continue; ComponentDefinitionIR * depDef; if (depDefs.TryGetValue(depWorld, depDef)) { comp->Dependency.Add(depDef); depDef->Users.Add(comp.Ptr()); // add additional dependencies due to import operators if (depWorld != comp->World) { auto importPath = Shader->Pipeline->FindImportOperatorChain(depWorld, comp->World); if (importPath.Count() == 0) throw InvalidProgramException(L"no import path found."); auto & usings = importPath.First().Nodes.Last().ImportOperator->Usings; for (auto & importUsing : usings) { ShaderComponentSymbol* refComp; if (!Shader->AllComponents.TryGetValue(importUsing.Content, refComp)) throw InvalidProgramException(L"import operator dependency not exists."); workList.Add(refComp); } } goto selectionEnd; // first preferred overload is found, terminate searching } } } selectionEnd:; } } }
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); } }
protected: HashSetTest() { set_.Add("1"); set_.Add("2"); set_.Add("3"); }
/* Generate a shader variant by applying mechanic choice rules and the choice file. The choice file provides "preferred" definitions, as represented in ShaderComponentSymbol::Type::PinnedWorlds The process resolves the component references by picking a pinned definition if one is available, or a definition with the preferred import path as defined by import operator ordering. After all references are resolved, all unreferenced definitions (dead code) are eliminated, resulting a shader variant ready for code generation. */ RefPtr<ShaderIR> GenerateShaderVariantIR(CompileResult & cresult, ShaderClosure * shader, Schedule & schedule, SymbolTable * symbolTable) { RefPtr<ShaderIR> result = new ShaderIR(); result->Shader = shader; result->SymbolTable = symbolTable; // mark pinned worlds for (auto & comp : shader->Components) { for (auto & impl : comp.Value->Implementations) { for (auto & w : impl->Worlds) { if (impl->SrcPinnedWorlds.Contains(w) || impl->SyntaxNode->IsInline() || impl->ExportWorlds.Contains(w) || impl->SyntaxNode->IsInput()) { comp.Value->Type->PinnedWorlds.Add(w); } } } } // apply choices Dictionary<String, ShaderComponentSymbol*> choiceComps; for (auto & comp : shader->AllComponents) { for (auto & choiceName : comp.Value.Symbol->ChoiceNames) choiceComps[choiceName] = comp.Value.Symbol; } HashSet<ShaderComponentImplSymbol*> pinnedImpl; for (auto & choice : schedule.Choices) { ShaderComponentSymbol * comp = nullptr; if (choiceComps.TryGetValue(choice.Key, comp)) { comp->Type->PinnedWorlds.Clear(); for (auto & selectedDef : choice.Value) { if (comp->Type->ConstrainedWorlds.Contains(selectedDef->WorldName)) { comp->Type->PinnedWorlds.Add(selectedDef->WorldName); // find specified impl for (auto & impl : comp->Implementations) { if (impl->Worlds.Contains(selectedDef->WorldName)) pinnedImpl.Add(impl.Ptr()); } } else { cresult.GetErrorWriter()->diagnose(selectedDef.Ptr()->Position, Diagnostics::worldIsNotAValidChoiceForKey, selectedDef->WorldName, choice.Key); } } } } for (auto & attribs : schedule.AddtionalAttributes) { ShaderComponentSymbol * comp = nullptr; if (choiceComps.TryGetValue(attribs.Key, comp)) { // apply attributes for (auto & impl : comp->Implementations) { for (auto & attrib : attribs.Value) { auto modifier = new SimpleAttribute(); modifier->Key = attrib.Key; modifier->Value.Content = attrib.Value; modifier->next = impl->SyntaxNode->modifiers.first; impl->SyntaxNode->modifiers.first = modifier; } } } } // generate definitions Dictionary<ShaderClosure*, ModuleInstanceIR*> moduleInstanceMap; auto createModuleInstance = [&](ShaderClosure * closure) { ModuleInstanceIR * inst; if (moduleInstanceMap.TryGetValue(closure, inst)) return inst; List<String> namePath; auto parent = closure; while (parent) { if (parent->Name.Length()) namePath.Add(parent->Name); else namePath.Add(parent->ModuleSyntaxNode->Name.Content); parent = parent->Parent; } StringBuilder sbBindingName; for (int i = namePath.Count() - 2; i >= 0; i--) { sbBindingName << namePath[i]; if (i > 0) sbBindingName << "."; } // if this is the root module, its binding name is module name. if (namePath.Count() == 1) sbBindingName << namePath[0]; inst = new ModuleInstanceIR(); inst->SyntaxNode = closure->ModuleSyntaxNode; inst->BindingIndex = closure->BindingIndex; inst->UsingPosition = closure->UsingPosition; result->ModuleInstances.Add(inst); inst->BindingName = sbBindingName.ProduceString(); moduleInstanceMap[closure] = inst; return inst; }; for (auto & comp : shader->AllComponents) { EnumerableDictionary<String, ComponentDefinitionIR*> defs; Dictionary<String, ShaderComponentImplSymbol*> impls; for (auto & impl : comp.Value.Symbol->Implementations) { auto createComponentDef = [&](const String & w) { RefPtr<ComponentDefinitionIR> def = new ComponentDefinitionIR(); def->OriginalName = comp.Value.Symbol->Name; def->UniqueKey = comp.Value.Symbol->UniqueKey; def->UniqueName = comp.Value.Symbol->UniqueName; def->Type = comp.Value.Symbol->Type->DataType; def->IsEntryPoint = (impl->ExportWorlds.Contains(w) || impl->SyntaxNode->IsParam() || (shader->Pipeline->IsAbstractWorld(w) && (impl->SyntaxNode->HasSimpleAttribute("Pinned") || shader->Pipeline->Worlds[w]()->HasSimpleAttribute("Pinned")))); CloneContext cloneCtx; def->SyntaxNode = impl->SyntaxNode->Clone(cloneCtx); def->World = w; def->ModuleInstance = createModuleInstance(comp.Value.Closure); return def; }; // parameter component will only have one defintion that is shared by all worlds if (impl->SyntaxNode->IsParam()) { auto def = createComponentDef("<uniform>"); result->Definitions.Add(def); defs["<uniform>"] = def.Ptr(); } else { for (auto & w : impl->Worlds) { auto def = createComponentDef(w); result->Definitions.Add(def); bool existingDefIsPinned = false; if (defs.ContainsKey(w)) existingDefIsPinned = pinnedImpl.Contains(impls[w]()); if (!existingDefIsPinned) { defs[w] = def.Ptr(); impls[w] = impl.Ptr(); } } } } result->DefinitionsByComponent[comp.Key] = defs; } bool changed = true; while (changed) { changed = false; result->ResolveComponentReference(); result->EliminateDeadCode(); // check circular references for (auto & def : result->Definitions) { if (def->Dependency.Contains(def.Ptr())) { cresult.GetErrorWriter()->diagnose(def->SyntaxNode->Position, Diagnostics::componentDefinitionCircularity, def->OriginalName); return nullptr; } } /* // eliminate redundant (downstream) definitions, one at a time auto comps = result->GetComponentDependencyOrder(); for (int i = comps.Count() - 1; i >= 0; i--) { auto comp = comps[i]; auto & defs = result->DefinitionsByComponent[comp->UniqueName](); EnumerableHashSet<ComponentDefinitionIR*> removedDefs; for (auto & def : defs) if (!def.Value->IsEntryPoint && !comp->Type->PinnedWorlds.Contains(def.Value->World)) { for (auto & otherDef : defs) { if (otherDef.Value != def.Value && !removedDefs.Contains(otherDef.Value) && shader->Pipeline->IsWorldReachable(otherDef.Value->World, def.Value->World)) { removedDefs.Add(def.Value); break; } } } if (removedDefs.Count()) { result->RemoveDefinitions([&](ComponentDefinitionIR* def) {return removedDefs.Contains(def); }); changed = true; } } */ } return result; }