| 118 | }; |
| 119 | |
| 120 | void ShaderIR::ResolveComponentReference() |
| 121 | { |
| 122 | // build bidirectional dependency map of component definitions |
| 123 | for (auto & comp : Definitions) |
| 124 | { |
| 125 | comp->Dependency.Clear(); |
| 126 | comp->Users.Clear(); |
| 127 | } |
| 128 | for (auto & comp : Definitions) |
| 129 | { |
| 130 | List<ReferenceWorkItem> workList; |
| 131 | for (auto & dep : GetDependentComponents(comp->SyntaxNode.Ptr())) |
| 132 | { |
| 133 | ReferenceWorkItem item; |
| 134 | item.Dependency = dep; |
| 135 | item.SourceWorld = dep.ImportOperator ? dep.ImportOperator->SourceWorld.Content : comp->World; |
| 136 | workList.Add(item); |
| 137 | } |
| 138 | HashSet<ReferenceWorkItem> proceseedDefCompss; |
| 139 | for (int i = 0; i < workList.Count(); i++) |
| 140 | { |
| 141 | auto dep = workList[i]; |
| 142 | if (!proceseedDefCompss.Add(dep)) |
| 143 | continue; |
| 144 | auto & depDefs = DefinitionsByComponent[dep.Dependency.ReferencedComponent](); |
| 145 | // select the best overload according to import operator ordering, |
| 146 | // prefer user-pinned definitions (as provided in the choice file) |
| 147 | List<String> depWorlds; |
| 148 | depWorlds.Add(dep.SourceWorld); |
| 149 | for (auto & w : Shader->Pipeline->WorldDependency[dep.SourceWorld]()) |
| 150 | depWorlds.Add(w); |
| 151 | depWorlds.Add("<uniform>"); |
| 152 | for (int pass = 0; pass < 2; pass++) |
| 153 | { |
| 154 | // in the first pass, examine the pinned definitions only |
| 155 | // in the second pass, examine all the rest definitions |
| 156 | for (auto & depWorld : depWorlds) |
| 157 | { |
| 158 | auto refComp = Shader->AllComponents[dep.Dependency.ReferencedComponent](); |
| 159 | bool isPinned = refComp.Symbol->Type->PinnedWorlds.Contains(depWorld); |
| 160 | if ((pass == 0 && !isPinned) || (pass == 1 && isPinned)) continue; |
| 161 | ComponentDefinitionIR * depDef; |
| 162 | if (depDefs.TryGetValue(depWorld, depDef)) |
| 163 | { |
| 164 | comp->Dependency.Add(depDef); |
| 165 | depDef->Users.Add(comp.Ptr()); |
| 166 | // add additional dependencies due to import operators |
| 167 | auto processImportOperatorUsings = [&](ImportOperatorDefSyntaxNode * importOp) |
| 168 | { |
| 169 | for (auto & importUsing : importOp->Usings) |
| 170 | { |
| 171 | ComponentInstance refComp; |
| 172 | if (!Shader->AllComponents.TryGetValue(importUsing, refComp)) |
| 173 | throw InvalidProgramException("import operator dependency not exists."); |
| 174 | ReferenceWorkItem workItem; |
| 175 | workItem.Dependency = ComponentDependency(refComp.Symbol->UniqueName, nullptr); |
| 176 | workItem.SourceWorld = importOp->SourceWorld.Content; |
| 177 | workList.Add(workItem); |
no test coverage detected