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
30using std::vector;
31using std::set;
32using std::map;
33
34namespace rsg
35{
36
37class SubValueRangeIterator
38{
39public:
40									SubValueRangeIterator			(const ConstValueRangeAccess& valueRange);
41									~SubValueRangeIterator			(void) {}
42
43	bool							hasItem							(void) const;
44	ConstValueRangeAccess			getItem							(void) const;
45	void							next							(void);
46
47private:
48
49	vector<ConstValueRangeAccess>	m_stack;
50};
51
52SubValueRangeIterator::SubValueRangeIterator (const ConstValueRangeAccess& valueRange)
53{
54	m_stack.push_back(valueRange);
55}
56
57inline bool SubValueRangeIterator::hasItem (void) const
58{
59	return !m_stack.empty();
60}
61
62inline ConstValueRangeAccess SubValueRangeIterator::getItem (void) const
63{
64	return m_stack[m_stack.size()-1];
65}
66
67void 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
95ValueEntry::ValueEntry (const Variable* variable)
96	: m_variable	(variable)
97	, m_valueRange	(variable->getType())
98{
99}
100
101VariableScope::VariableScope (void)
102{
103}
104
105VariableScope::~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
114Variable* 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
129void VariableScope::declare (Variable* variable)
130{
131	m_declaredVariables.push_back(variable);
132	removeLive(variable);
133}
134
135void 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
144ValueScope::ValueScope (void)
145{
146}
147
148ValueScope::~ValueScope (void)
149{
150	clear();
151}
152
153void 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
160ValueEntry* 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
175class CompareEntryVariable
176{
177public:
178	CompareEntryVariable (const Variable* variable)
179		: m_variable(variable)
180	{
181	}
182
183	bool operator== (const ValueEntry* entry) const
184	{
185		return entry->getVariable() == m_variable;
186	}
187
188private:
189	const Variable* m_variable;
190};
191
192bool operator== (const ValueEntry* entry, const CompareEntryVariable& cmp)
193{
194	return cmp == entry;
195}
196
197ValueEntry* 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
203void 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
213void 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
224VariableManager::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
233VariableManager::~VariableManager (void)
234{
235}
236
237Variable* VariableManager::allocate (const VariableType& type)
238{
239	return allocate(type, Variable::STORAGE_LOCAL, m_nameAllocator.allocate().c_str());
240}
241
242Variable* 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
265void 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
290bool 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
296const vector<Variable*>& VariableManager::getLiveVariables (void) const
297{
298	return getCurVariableScope().getLiveVariables();
299}
300
301void 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
321const 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
327void 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
338const 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
355void 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
374void VariableManager::reserve (ReservedScalars& store, int numScalars)
375{
376	DE_ASSERT(store.numScalars == 0);
377	store.numScalars		 = numScalars;
378	m_numAllocatedScalars	+= numScalars;
379}
380
381void VariableManager::release (ReservedScalars& store)
382{
383	m_numAllocatedScalars	-= store.numScalars;
384	store.numScalars		 = 0;
385}
386
387void 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
396void 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
422void 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
430void 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);
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