xref: /aosp_15_r20/external/deqp/framework/randomshaders/rsgVariableManager.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Random Shader Generator
3  * ----------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Variable manager.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "rsgVariableManager.hpp"
25 
26 #include <algorithm>
27 #include <map>
28 #include <set>
29 
30 using std::map;
31 using std::set;
32 using std::vector;
33 
34 namespace rsg
35 {
36 
37 class SubValueRangeIterator
38 {
39 public:
40     SubValueRangeIterator(const ConstValueRangeAccess &valueRange);
~SubValueRangeIterator(void)41     ~SubValueRangeIterator(void)
42     {
43     }
44 
45     bool hasItem(void) const;
46     ConstValueRangeAccess getItem(void) const;
47     void next(void);
48 
49 private:
50     vector<ConstValueRangeAccess> m_stack;
51 };
52 
SubValueRangeIterator(const ConstValueRangeAccess & valueRange)53 SubValueRangeIterator::SubValueRangeIterator(const ConstValueRangeAccess &valueRange)
54 {
55     m_stack.push_back(valueRange);
56 }
57 
hasItem(void) const58 inline bool SubValueRangeIterator::hasItem(void) const
59 {
60     return !m_stack.empty();
61 }
62 
getItem(void) const63 inline ConstValueRangeAccess SubValueRangeIterator::getItem(void) const
64 {
65     return m_stack[m_stack.size() - 1];
66 }
67 
next(void)68 void SubValueRangeIterator::next(void)
69 {
70     ConstValueRangeAccess curItem = getItem();
71     m_stack.pop_back(); // Remove current
72 
73     switch (curItem.getType().getBaseType())
74     {
75     case VariableType::TYPE_ARRAY:
76     {
77         int numElements = curItem.getType().getNumElements();
78         for (int ndx = 0; ndx < numElements; ndx++)
79             m_stack.push_back(curItem.member(ndx));
80         break;
81     }
82 
83     case VariableType::TYPE_STRUCT:
84     {
85         int numMembers = (int)curItem.getType().getMembers().size();
86         for (int ndx = 0; ndx < numMembers; ndx++)
87             m_stack.push_back(curItem.member(ndx));
88         break;
89     }
90 
91     default:
92         break; // \todo [2011-02-03 pyry] Swizzle control?
93     }
94 }
95 
ValueEntry(const Variable * variable)96 ValueEntry::ValueEntry(const Variable *variable) : m_variable(variable), m_valueRange(variable->getType())
97 {
98 }
99 
VariableScope(void)100 VariableScope::VariableScope(void)
101 {
102 }
103 
~VariableScope(void)104 VariableScope::~VariableScope(void)
105 {
106     for (vector<Variable *>::iterator i = m_declaredVariables.begin(); i != m_declaredVariables.end(); i++)
107         delete *i;
108 
109     for (vector<Variable *>::iterator i = m_liveVariables.begin(); i != m_liveVariables.end(); i++)
110         delete *i;
111 }
112 
allocate(const VariableType & type,Variable::Storage storage,const char * name)113 Variable *VariableScope::allocate(const VariableType &type, Variable::Storage storage, const char *name)
114 {
115     Variable *variable = new Variable(type, storage, name);
116     try
117     {
118         m_liveVariables.push_back(variable);
119         return variable;
120     }
121     catch (const std::exception &)
122     {
123         delete variable;
124         throw;
125     }
126 }
127 
declare(Variable * variable)128 void VariableScope::declare(Variable *variable)
129 {
130     m_declaredVariables.push_back(variable);
131     removeLive(variable);
132 }
133 
removeLive(const Variable * variable)134 void VariableScope::removeLive(const Variable *variable)
135 {
136     vector<Variable *>::iterator pos = std::find(m_liveVariables.begin(), m_liveVariables.end(), variable);
137     DE_ASSERT(pos != m_liveVariables.end());
138 
139     // \todo [pyry] Not so efficient
140     m_liveVariables.erase(pos);
141 }
142 
ValueScope(void)143 ValueScope::ValueScope(void)
144 {
145 }
146 
~ValueScope(void)147 ValueScope::~ValueScope(void)
148 {
149     clear();
150 }
151 
clear(void)152 void ValueScope::clear(void)
153 {
154     for (vector<ValueEntry *>::iterator i = m_entries.begin(); i != m_entries.end(); i++)
155         delete *i;
156     m_entries.clear();
157 }
158 
allocate(const Variable * variable)159 ValueEntry *ValueScope::allocate(const Variable *variable)
160 {
161     ValueEntry *entry = new ValueEntry(variable);
162     try
163     {
164         m_entries.push_back(entry);
165         return entry;
166     }
167     catch (const std::exception &)
168     {
169         delete entry;
170         throw;
171     }
172 }
173 
174 class CompareEntryVariable
175 {
176 public:
CompareEntryVariable(const Variable * variable)177     CompareEntryVariable(const Variable *variable) : m_variable(variable)
178     {
179     }
180 
operator ==(const ValueEntry * entry) const181     bool operator==(const ValueEntry *entry) const
182     {
183         return entry->getVariable() == m_variable;
184     }
185 
186 private:
187     const Variable *m_variable;
188 };
189 
operator ==(const ValueEntry * entry,const CompareEntryVariable & cmp)190 bool operator==(const ValueEntry *entry, const CompareEntryVariable &cmp)
191 {
192     return cmp == entry;
193 }
194 
findEntry(const Variable * variable) const195 ValueEntry *ValueScope::findEntry(const Variable *variable) const
196 {
197     vector<ValueEntry *>::const_iterator pos =
198         std::find(m_entries.begin(), m_entries.end(), CompareEntryVariable(variable));
199     return pos != m_entries.end() ? *pos : DE_NULL;
200 }
201 
setValue(const Variable * variable,ConstValueRangeAccess value)202 void ValueScope::setValue(const Variable *variable, ConstValueRangeAccess value)
203 {
204     ValueEntry *entry = findEntry(variable);
205     DE_ASSERT(entry);
206 
207     ValueRangeAccess dst = entry->getValueRange();
208     dst.getMin()         = value.getMin().value();
209     dst.getMax()         = value.getMax().value();
210 }
211 
removeValue(const Variable * variable)212 void ValueScope::removeValue(const Variable *variable)
213 {
214     vector<ValueEntry *>::iterator pos = std::find(m_entries.begin(), m_entries.end(), CompareEntryVariable(variable));
215     if (pos != m_entries.end())
216     {
217         ValueEntry *entry = *pos;
218         m_entries.erase(pos);
219         delete entry;
220     }
221 }
222 
VariableManager(NameAllocator & nameAllocator)223 VariableManager::VariableManager(NameAllocator &nameAllocator)
224     : m_numAllocatedScalars(0)
225     , m_numAllocatedShaderInScalars(0)
226     , m_numAllocatedShaderInVariables(0)
227     , m_numAllocatedUniformScalars(0)
228     , m_nameAllocator(nameAllocator)
229 {
230 }
231 
~VariableManager(void)232 VariableManager::~VariableManager(void)
233 {
234 }
235 
allocate(const VariableType & type)236 Variable *VariableManager::allocate(const VariableType &type)
237 {
238     return allocate(type, Variable::STORAGE_LOCAL, m_nameAllocator.allocate().c_str());
239 }
240 
allocate(const VariableType & type,Variable::Storage storage,const char * name)241 Variable *VariableManager::allocate(const VariableType &type, Variable::Storage storage, const char *name)
242 {
243     VariableScope &varScope = getCurVariableScope();
244     ValueScope &valueScope  = getCurValueScope();
245     int numScalars          = type.getScalarSize();
246 
247     // Allocate in current scope
248     Variable *variable = varScope.allocate(type, Variable::STORAGE_LOCAL, name);
249 
250     // Allocate value entry
251     ValueEntry *valueEntry = valueScope.allocate(variable);
252 
253     // Add to cache
254     m_entryCache.push_back(valueEntry);
255 
256     m_numAllocatedScalars += numScalars;
257 
258     // Set actual storage - affects uniform/shader in allocations.
259     setStorage(variable, storage);
260 
261     return variable;
262 }
263 
setStorage(Variable * variable,Variable::Storage storage)264 void VariableManager::setStorage(Variable *variable, Variable::Storage storage)
265 {
266     int numScalars = variable->getType().getScalarSize();
267 
268     // Decrement old.
269     if (variable->getStorage() == Variable::STORAGE_SHADER_IN)
270     {
271         m_numAllocatedShaderInScalars -= numScalars;
272         m_numAllocatedShaderInVariables -= 1;
273     }
274     else if (variable->getStorage() == Variable::STORAGE_UNIFORM)
275         m_numAllocatedUniformScalars -= numScalars;
276 
277     // Add new.
278     if (storage == Variable::STORAGE_SHADER_IN)
279     {
280         m_numAllocatedShaderInScalars += numScalars;
281         m_numAllocatedShaderInVariables += 1;
282     }
283     else if (storage == Variable::STORAGE_UNIFORM)
284         m_numAllocatedUniformScalars += numScalars;
285 
286     variable->setStorage(storage);
287 }
288 
canDeclareInCurrentScope(const Variable * variable) const289 bool VariableManager::canDeclareInCurrentScope(const Variable *variable) const
290 {
291     const vector<Variable *> &curLiveVars = getCurVariableScope().getLiveVariables();
292     return std::find(curLiveVars.begin(), curLiveVars.end(), variable) != curLiveVars.end();
293 }
294 
getLiveVariables(void) const295 const vector<Variable *> &VariableManager::getLiveVariables(void) const
296 {
297     return getCurVariableScope().getLiveVariables();
298 }
299 
declareVariable(Variable * variable)300 void VariableManager::declareVariable(Variable *variable)
301 {
302     // Remove from cache if exists in there.
303     std::vector<const ValueEntry *>::iterator pos =
304         std::find(m_entryCache.begin(), m_entryCache.end(), CompareEntryVariable(variable));
305     if (pos != m_entryCache.end())
306         m_entryCache.erase(pos);
307 
308     DE_ASSERT(std::find(m_entryCache.begin(), m_entryCache.end(), CompareEntryVariable(variable)) ==
309               m_entryCache.end());
310 
311     // Remove from scope stack.
312     for (vector<ValueScope *>::const_iterator stackIter = m_valueScopeStack.begin();
313          stackIter != m_valueScopeStack.end(); stackIter++)
314     {
315         ValueScope *scope = *stackIter;
316         scope->removeValue(variable);
317     }
318 
319     // Declare in current scope.
320     getCurVariableScope().declare(variable);
321 }
322 
getValue(const Variable * variable) const323 const ValueEntry *VariableManager::getValue(const Variable *variable) const
324 {
325     vector<const ValueEntry *>::const_iterator pos =
326         std::find(m_entryCache.begin(), m_entryCache.end(), CompareEntryVariable(variable));
327     return pos != m_entryCache.end() ? *pos : DE_NULL;
328 }
329 
removeValueFromCurrentScope(const Variable * variable)330 void VariableManager::removeValueFromCurrentScope(const Variable *variable)
331 {
332     // Remove from cache
333     std::vector<const ValueEntry *>::iterator pos =
334         std::find(m_entryCache.begin(), m_entryCache.end(), CompareEntryVariable(variable));
335     DE_ASSERT(pos != m_entryCache.end());
336     m_entryCache.erase(pos);
337 
338     // Remove from current scope \note May not exist in there.
339     getCurValueScope().removeValue(variable);
340 }
341 
getParentValue(const Variable * variable) const342 const ValueEntry *VariableManager::getParentValue(const Variable *variable) const
343 {
344     if (m_valueScopeStack.size() < 2)
345         return DE_NULL; // Only single value scope
346 
347     for (vector<ValueScope *>::const_reverse_iterator i = m_valueScopeStack.rbegin() + 1; i != m_valueScopeStack.rend();
348          i++)
349     {
350         const ValueScope *scope = *i;
351         ValueEntry *entry       = scope->findEntry(variable);
352 
353         if (entry)
354             return entry;
355     }
356 
357     return DE_NULL; // Not found in stack
358 }
359 
setValue(const Variable * variable,ConstValueRangeAccess value)360 void VariableManager::setValue(const Variable *variable, ConstValueRangeAccess value)
361 {
362     ValueScope &curScope = getCurValueScope();
363 
364     if (!curScope.findEntry(variable))
365     {
366         // New value, allocate and update cache.
367         ValueEntry *newEntry = curScope.allocate(variable);
368         std::vector<const ValueEntry *>::iterator cachePos =
369             std::find(m_entryCache.begin(), m_entryCache.end(), CompareEntryVariable(variable));
370 
371         if (cachePos != m_entryCache.end())
372             *cachePos = newEntry;
373         else
374             m_entryCache.push_back(newEntry);
375     }
376 
377     curScope.setValue(variable, value);
378 }
379 
reserve(ReservedScalars & store,int numScalars)380 void VariableManager::reserve(ReservedScalars &store, int numScalars)
381 {
382     DE_ASSERT(store.numScalars == 0);
383     store.numScalars = numScalars;
384     m_numAllocatedScalars += numScalars;
385 }
386 
release(ReservedScalars & store)387 void VariableManager::release(ReservedScalars &store)
388 {
389     m_numAllocatedScalars -= store.numScalars;
390     store.numScalars = 0;
391 }
392 
pushVariableScope(VariableScope & scope)393 void VariableManager::pushVariableScope(VariableScope &scope)
394 {
395     // Expects emtpy scope
396     DE_ASSERT(scope.getDeclaredVariables().size() == 0);
397     DE_ASSERT(scope.getLiveVariables().size() == 0);
398 
399     m_variableScopeStack.push_back(&scope);
400 }
401 
popVariableScope(void)402 void VariableManager::popVariableScope(void)
403 {
404     VariableScope &curScope = getCurVariableScope();
405 
406     // Migrate live variables to parent scope.
407     // Variables allocated in child scopes can be declared in any parent scope but not the other way around.
408     if (m_variableScopeStack.size() > 1)
409     {
410         VariableScope &parentScope        = *m_variableScopeStack[m_variableScopeStack.size() - 2];
411         vector<Variable *> &curLiveVars   = curScope.getLiveVariables();
412         vector<Variable *> &parenLiveVars = parentScope.getLiveVariables();
413 
414         while (!curLiveVars.empty())
415         {
416             Variable *liveVar = curLiveVars.back();
417             parenLiveVars.push_back(liveVar);
418             curLiveVars.pop_back();
419         }
420     }
421 
422     // All variables should be either migrated to parent or declared (in case of root scope).
423     DE_ASSERT(curScope.getLiveVariables().size() == 0);
424 
425     m_variableScopeStack.pop_back();
426 }
427 
pushValueScope(ValueScope & scope)428 void VariableManager::pushValueScope(ValueScope &scope)
429 {
430     // Value scope should be empty
431     DE_ASSERT(scope.getValues().size() == 0);
432 
433     m_valueScopeStack.push_back(&scope);
434 }
435 
popValueScope(void)436 void VariableManager::popValueScope(void)
437 {
438     ValueScope &oldScope = getCurValueScope();
439 
440     // Pop scope and clear cache.
441     m_valueScopeStack.pop_back();
442     m_entryCache.clear();
443 
444     // Re-build entry cache.
445     if (!m_valueScopeStack.empty())
446     {
447         ValueScope &newTopScope = getCurValueScope();
448 
449         // Speed up computing intersections.
450         map<const Variable *, const ValueEntry *> oldValues;
451         const vector<ValueEntry *> &oldEntries = oldScope.getValues();
452 
453         for (vector<ValueEntry *>::const_iterator valueIter = oldEntries.begin(); valueIter != oldEntries.end();
454              valueIter++)
455             oldValues[(*valueIter)->getVariable()] = *valueIter;
456 
457         set<const Variable *> addedVars;
458 
459         // Re-build based on current stack.
460         for (vector<ValueScope *>::reverse_iterator scopeIter = m_valueScopeStack.rbegin();
461              scopeIter != m_valueScopeStack.rend(); scopeIter++)
462         {
463             const ValueScope *scope                  = *scopeIter;
464             const vector<ValueEntry *> &valueEntries = scope->getValues();
465 
466             for (vector<ValueEntry *>::const_iterator valueIter = valueEntries.begin(); valueIter != valueEntries.end();
467                  valueIter++)
468             {
469                 const ValueEntry *entry = *valueIter;
470                 const Variable *var     = entry->getVariable();
471 
472                 if (addedVars.find(var) != addedVars.end())
473                     continue; // Already in cache, set deeper in scope stack.
474 
475                 DE_ASSERT(std::find(m_entryCache.begin(), m_entryCache.end(), CompareEntryVariable(var)) ==
476                           m_entryCache.end());
477 
478                 if (oldValues.find(var) != oldValues.end())
479                 {
480                     const ValueEntry *oldEntry = oldValues[var];
481 
482                     // Build new intersected value and store into current scope.
483                     ValueRange intersectedValue(var->getType());
484                     DE_ASSERT(oldEntry->getValueRange().intersects(entry->getValueRange())); // Must intersect
485                     ValueRange::computeIntersection(intersectedValue, entry->getValueRange(),
486                                                     oldEntry->getValueRange());
487 
488                     if (!newTopScope.findEntry(var))
489                         newTopScope.allocate(var);
490 
491                     newTopScope.setValue(var, intersectedValue.asAccess());
492 
493                     // Add entry from top scope to cache.
494                     m_entryCache.push_back(newTopScope.findEntry(var));
495                 }
496                 else
497                     m_entryCache.push_back(entry); // Just add to cache.
498 
499                 addedVars.insert(var); // Record as cached variable.
500             }
501         }
502 
503         // Copy entries from popped scope that don't yet exist in the stack.
504         for (vector<ValueEntry *>::const_iterator valueIter = oldEntries.begin(); valueIter != oldEntries.end();
505              valueIter++)
506         {
507             const ValueEntry *oldEntry = *valueIter;
508             const Variable *var        = oldEntry->getVariable();
509 
510             if (addedVars.find(var) == addedVars.end())
511                 setValue(var, oldEntry->getValueRange());
512         }
513     }
514 }
515 
516 } // namespace rsg
517