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