#ifndef _RSGVARIABLEMANAGER_HPP #define _RSGVARIABLEMANAGER_HPP /*------------------------------------------------------------------------- * drawElements Quality Program Random Shader Generator * ---------------------------------------------------- * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Variable manager. * * Memory management: * Variable manager owns variable objects until they are either explictly * removed or moved to currently active scope. After that the ownership * is transferred to Scope or the object that called removeEntry(). *//*--------------------------------------------------------------------*/ #include "rsgDefs.hpp" #include "rsgVariable.hpp" #include "rsgVariableValue.hpp" #include "rsgNameAllocator.hpp" #include #include #include namespace rsg { class ValueEntry { public: ValueEntry(const Variable *variable); ~ValueEntry(void) { } const Variable *getVariable(void) const { return m_variable; } ConstValueRangeAccess getValueRange(void) const { return m_valueRange.asAccess(); } ValueRangeAccess getValueRange(void) { return m_valueRange.asAccess(); } private: const Variable *m_variable; ValueRange m_valueRange; }; // Variable scope manages variable allocation. class VariableScope { public: VariableScope(void); ~VariableScope(void); Variable *allocate(const VariableType &type, Variable::Storage storage, const char *name); void declare(Variable *variable); //!< Move from live set to declared set void removeLive(const Variable *variable); //!< Just remove from live set (when migrating to parent). const std::vector &getDeclaredVariables(void) const { return m_declaredVariables; } std::vector &getLiveVariables(void) { return m_liveVariables; } const std::vector &getLiveVariables(void) const { return m_liveVariables; } private: VariableScope(const VariableScope &other); VariableScope &operator=(const VariableScope &other); std::vector m_declaredVariables; //!< Variables declared in this scope. Not available for expressions. std::vector m_liveVariables; //!< Live variables (available for expression) that can be declared in this scope. }; class ValueScope { public: ValueScope(void); ~ValueScope(void); ValueEntry *allocate(const Variable *variable); ValueEntry *findEntry(const Variable *variable) const; void setValue(const Variable *variable, ConstValueRangeAccess value); void removeValue(const Variable *variable); std::vector &getValues(void) { return m_entries; } const std::vector &getValues(void) const { return m_entries; } void clear(void); private: ValueScope(const ValueScope &other); ValueScope &operator=(const ValueScope &other); std::vector m_entries; }; class ReservedScalars { public: int numScalars; ReservedScalars(void) : numScalars(0) { } }; // \todo [2011-05-26 pyry] Clean up this a bit, separate const variant. template class FilteredIterator { public: using iterator_category = std::input_iterator_tag; using value_type = Item; using difference_type = std::ptrdiff_t; using pointer = Item *; using reference = Item &; FilteredIterator(Iterator iter, Iterator end, Filter filter) : m_iter(iter), m_end(end), m_filter(filter) { } FilteredIterator operator+(ptrdiff_t offset) const { Iterator nextEntry = m_iter; while (offset--) nextEntry = findNext(m_filter, nextEntry, m_end); return FilteredIterator(nextEntry, m_end, m_filter); } FilteredIterator &operator++() { // Pre-increment m_iter = findNext(m_filter, m_iter, m_end); return *this; } FilteredIterator operator++(int) { // Post-increment FilteredIterator copy = *this; m_iter = findNext(m_filter, m_iter, m_end); return copy; } bool operator==(const FilteredIterator &other) const { return m_iter == other.m_iter; } bool operator!=(const FilteredIterator &other) const { return m_iter != other.m_iter; } const Item &operator*(void) { DE_ASSERT(m_iter != m_end); DE_ASSERT(m_filter(*m_iter)); return *m_iter; } private: static Iterator findNext(Filter filter, Iterator iter, Iterator end) { do iter++; while (iter != end && !filter(*iter)); return iter; } Iterator m_iter; Iterator m_end; Filter m_filter; }; template class ValueEntryIterator : public FilteredIterator::const_iterator, Filter> { public: ValueEntryIterator(std::vector::const_iterator begin, std::vector::const_iterator end, Filter filter) : FilteredIterator::const_iterator, Filter>(begin, end, filter) { } }; class VariableManager { public: VariableManager(NameAllocator &nameAllocator); ~VariableManager(void); int getNumAllocatedScalars(void) const { return m_numAllocatedScalars; } int getNumAllocatedShaderInScalars(void) const { return m_numAllocatedShaderInScalars; } int getNumAllocatedShaderInVariables(void) const { return m_numAllocatedShaderInVariables; } int getNumAllocatedUniformScalars(void) const { return m_numAllocatedUniformScalars; } void reserve(ReservedScalars &store, int numScalars); void release(ReservedScalars &store); Variable *allocate(const VariableType &type); Variable *allocate(const VariableType &type, Variable::Storage storage, const char *name); void setStorage(Variable *variable, Variable::Storage storage); void setValue(const Variable *variable, ConstValueRangeAccess value); const ValueEntry *getValue(const Variable *variable) const; const ValueEntry *getParentValue(const Variable *variable) const; void removeValueFromCurrentScope(const Variable *variable); void declareVariable(Variable *variable); bool canDeclareInCurrentScope(const Variable *variable) const; const std::vector &getLiveVariables(void) const; void pushVariableScope(VariableScope &scope); void popVariableScope(void); void pushValueScope(ValueScope &scope); void popValueScope(void); template ValueEntryIterator getBegin(Filter filter = Filter()) const; template ValueEntryIterator getEnd(Filter filter = Filter()) const; template bool hasEntry(Filter filter = Filter()) const; private: VariableManager(const VariableManager &other); VariableManager &operator=(const VariableManager &other); VariableScope &getCurVariableScope(void) { return *m_variableScopeStack.back(); } const VariableScope &getCurVariableScope(void) const { return *m_variableScopeStack.back(); } ValueScope &getCurValueScope(void) { return *m_valueScopeStack.back(); } const ValueScope &getCurValueScope(void) const { return *m_valueScopeStack.back(); } std::vector m_variableScopeStack; std::vector m_valueScopeStack; std::vector m_entryCache; //!< For faster value entry access. int m_numAllocatedScalars; int m_numAllocatedShaderInScalars; int m_numAllocatedShaderInVariables; int m_numAllocatedUniformScalars; NameAllocator &m_nameAllocator; }; template ValueEntryIterator VariableManager::getBegin(Filter filter) const { std::vector::const_iterator first = m_entryCache.begin(); while (first != m_entryCache.end() && !filter(*first)) first++; return ValueEntryIterator(first, m_entryCache.end(), filter); } template ValueEntryIterator VariableManager::getEnd(Filter filter) const { return ValueEntryIterator(m_entryCache.end(), m_entryCache.end(), filter); } template bool VariableManager::hasEntry(Filter filter) const { for (std::vector::const_iterator i = m_entryCache.begin(); i != m_entryCache.end(); i++) { if (filter(*i)) return true; } return false; } // Common filters class AnyEntry { public: typedef ValueEntryIterator Iterator; bool operator()(const ValueEntry *entry) const { DE_UNREF(entry); return true; } }; class IsWritableEntry { public: bool operator()(const ValueEntry *entry) const { switch (entry->getVariable()->getStorage()) { case Variable::STORAGE_LOCAL: case Variable::STORAGE_SHADER_OUT: case Variable::STORAGE_PARAMETER_IN: case Variable::STORAGE_PARAMETER_OUT: case Variable::STORAGE_PARAMETER_INOUT: return true; default: return false; } } }; template class EntryStorageFilter { public: typedef ValueEntryIterator> Iterator; bool operator()(const ValueEntry *entry) const { return entry->getVariable()->getStorage() == Storage; } }; typedef EntryStorageFilter LocalEntryFilter; typedef EntryStorageFilter ShaderInEntryFilter; typedef EntryStorageFilter ShaderOutEntryFilter; } // namespace rsg #endif // _RSGVARIABLEMANAGER_HPP