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); 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 52 SubValueRangeIterator::SubValueRangeIterator (const ConstValueRangeAccess& valueRange) 53 { 54 m_stack.push_back(valueRange); 55 } 56 57 inline bool SubValueRangeIterator::hasItem (void) const 58 { 59 return !m_stack.empty(); 60 } 61 62 inline ConstValueRangeAccess SubValueRangeIterator::getItem (void) const 63 { 64 return m_stack[m_stack.size()-1]; 65 } 66 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 95 ValueEntry::ValueEntry (const Variable* variable) 96 : m_variable (variable) 97 , m_valueRange (variable->getType()) 98 { 99 } 100 101 VariableScope::VariableScope (void) 102 { 103 } 104 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 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 129 void VariableScope::declare (Variable* variable) 130 { 131 m_declaredVariables.push_back(variable); 132 removeLive(variable); 133 } 134 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 144 ValueScope::ValueScope (void) 145 { 146 } 147 148 ValueScope::~ValueScope (void) 149 { 150 clear(); 151 } 152 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 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: 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 188 private: 189 const Variable* m_variable; 190 }; 191 192 bool operator== (const ValueEntry* entry, const CompareEntryVariable& cmp) 193 { 194 return cmp == entry; 195 } 196 197 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 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 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 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 233 VariableManager::~VariableManager (void) 234 { 235 } 236 237 Variable* VariableManager::allocate (const VariableType& type) 238 { 239 return allocate(type, Variable::STORAGE_LOCAL, m_nameAllocator.allocate().c_str()); 240 } 241 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 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 290 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 296 const vector<Variable*>& VariableManager::getLiveVariables (void) const 297 { 298 return getCurVariableScope().getLiveVariables(); 299 } 300 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 321 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 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 338 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 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 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 381 void VariableManager::release (ReservedScalars& store) 382 { 383 m_numAllocatedScalars -= store.numScalars; 384 store.numScalars = 0; 385 } 386 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 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 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 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