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