• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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