blob: 208cdb4da9a0a9a9e21d43c5b24e880998110ecd [file] [log] [blame]
#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 <iterator>
#include <vector>
#include <set>
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<Variable*>& getDeclaredVariables (void) const { return m_declaredVariables; }
std::vector<Variable*>& getLiveVariables (void) { return m_liveVariables; }
const std::vector<Variable*>& getLiveVariables (void) const { return m_liveVariables; }
private:
VariableScope (const VariableScope& other);
VariableScope& operator= (const VariableScope& other);
std::vector<Variable*> m_declaredVariables; //!< Variables declared in this scope. Not available for expressions.
std::vector<Variable*> 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<ValueEntry*>& getValues (void) { return m_entries; }
const std::vector<ValueEntry*>& getValues (void) const { return m_entries; }
void clear (void);
private:
ValueScope (const ValueScope& other);
ValueScope& operator= (const ValueScope& other);
std::vector<ValueEntry*> 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 <typename Item, typename Iterator, class Filter>
class FilteredIterator : public std::iterator<std::input_iterator_tag, Item>
{
public:
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 Filter>
class ValueEntryIterator : public FilteredIterator<const ValueEntry*, std::vector<const ValueEntry*>::const_iterator, Filter>
{
public:
ValueEntryIterator (std::vector<const ValueEntry*>::const_iterator begin, std::vector<const ValueEntry*>::const_iterator end, Filter filter)
: FilteredIterator<const ValueEntry*, std::vector<const ValueEntry*>::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<Variable*>& getLiveVariables (void) const;
void pushVariableScope (VariableScope& scope);
void popVariableScope (void);
void pushValueScope (ValueScope& scope);
void popValueScope (void);
template <class Filter>
ValueEntryIterator<Filter> getBegin (Filter filter = Filter()) const;
template <class Filter>
ValueEntryIterator<Filter> getEnd (Filter filter = Filter()) const;
template <class Filter>
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<VariableScope*> m_variableScopeStack;
std::vector<ValueScope*> m_valueScopeStack;
std::vector<const ValueEntry*> m_entryCache; //!< For faster value entry access.
int m_numAllocatedScalars;
int m_numAllocatedShaderInScalars;
int m_numAllocatedShaderInVariables;
int m_numAllocatedUniformScalars;
NameAllocator& m_nameAllocator;
};
template <class Filter>
ValueEntryIterator<Filter> VariableManager::getBegin (Filter filter) const
{
std::vector<const ValueEntry*>::const_iterator first = m_entryCache.begin();
while (first != m_entryCache.end() && !filter(*first))
first++;
return ValueEntryIterator<Filter>(first, m_entryCache.end(), filter);
}
template <class Filter>
ValueEntryIterator<Filter> VariableManager::getEnd (Filter filter) const
{
return ValueEntryIterator<Filter>(m_entryCache.end(), m_entryCache.end(), filter);
}
template <class Filter>
bool VariableManager::hasEntry (Filter filter) const
{
for (std::vector<const ValueEntry*>::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<AnyEntry> 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 <Variable::Storage Storage>
class EntryStorageFilter
{
public:
typedef ValueEntryIterator<EntryStorageFilter<Storage> > Iterator;
bool operator() (const ValueEntry* entry) const
{
return entry->getVariable()->getStorage() == Storage;
}
};
typedef EntryStorageFilter<Variable::STORAGE_LOCAL> LocalEntryFilter;
typedef EntryStorageFilter<Variable::STORAGE_SHADER_IN> ShaderInEntryFilter;
typedef EntryStorageFilter<Variable::STORAGE_SHADER_OUT> ShaderOutEntryFilter;
} // rsg
#endif // _RSGVARIABLEMANAGER_HPP