blob: eb32ccfe4502f90af0451d1b048936904733a3a3 [file] [log] [blame]
#ifndef _RSGVARIABLEVALUE_HPP
#define _RSGVARIABLEVALUE_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 Value class.
*//*--------------------------------------------------------------------*/
#include "rsgDefs.hpp"
#include "rsgVariableType.hpp"
#include "rsgVariable.hpp"
#include "tcuVector.hpp"
#include <algorithm>
namespace rsg
{
union Scalar
{
int intVal;
float floatVal;
bool boolVal;
Scalar(void) : intVal(0)
{
}
Scalar(float v) : floatVal(v)
{
}
Scalar(int v) : intVal(v)
{
}
Scalar(bool v) : boolVal(v)
{
}
// Bit-exact compare
bool operator==(Scalar other) const
{
return intVal == other.intVal;
}
bool operator!=(Scalar other) const
{
return intVal != other.intVal;
}
template <typename T>
static Scalar min(void);
template <typename T>
static Scalar max(void);
template <typename T>
T as(void) const;
template <typename T>
T &as(void);
};
DE_STATIC_ASSERT(sizeof(Scalar) == sizeof(uint32_t));
template <>
inline Scalar Scalar::min<float>(void)
{
return Scalar((int)0xff800000);
}
template <>
inline Scalar Scalar::max<float>(void)
{
return Scalar((int)0x7f800000);
}
template <>
inline Scalar Scalar::min<int>(void)
{
return Scalar((int)0x80000000);
}
template <>
inline Scalar Scalar::max<int>(void)
{
return Scalar((int)0x7fffffff);
}
template <>
inline Scalar Scalar::min<bool>(void)
{
return Scalar(false);
}
template <>
inline Scalar Scalar::max<bool>(void)
{
return Scalar(true);
}
template <>
inline float Scalar::as<float>(void) const
{
return floatVal;
}
template <>
inline float &Scalar::as<float>(void)
{
return floatVal;
}
template <>
inline int Scalar::as<int>(void) const
{
return intVal;
}
template <>
inline int &Scalar::as<int>(void)
{
return intVal;
}
template <>
inline bool Scalar::as<bool>(void) const
{
return boolVal;
}
template <>
inline bool &Scalar::as<bool>(void)
{
return boolVal;
}
template <int Stride>
class StridedValueRead
{
public:
StridedValueRead(const VariableType &type, const Scalar *value) : m_type(type), m_value(value)
{
}
const VariableType &getType(void) const
{
return m_type;
}
const Scalar *getValuePtr(void) const
{
return m_value;
}
private:
const VariableType &m_type;
const Scalar *m_value;
};
template <int Stride>
class ConstStridedValueAccess
{
public:
ConstStridedValueAccess(void) : m_type(DE_NULL), m_value(DE_NULL)
{
}
ConstStridedValueAccess(const VariableType &type, const Scalar *valuePtr)
: m_type(&type)
, m_value(const_cast<Scalar *>(valuePtr))
{
}
const VariableType &getType(void) const
{
return *m_type;
}
// Read-only access
ConstStridedValueAccess component(int compNdx) const
{
return ConstStridedValueAccess(getType().getElementType(), m_value + Stride * compNdx);
}
ConstStridedValueAccess arrayElement(int elementNdx) const
{
return ConstStridedValueAccess(getType().getElementType(),
m_value + Stride * getType().getElementScalarOffset(elementNdx));
}
ConstStridedValueAccess member(int memberNdx) const
{
return ConstStridedValueAccess(getType().getMembers()[memberNdx].getType(),
m_value + Stride * getType().getMemberScalarOffset(memberNdx));
}
float asFloat(void) const
{
DE_STATIC_ASSERT(Stride == 1);
return m_value->floatVal;
}
int asInt(void) const
{
DE_STATIC_ASSERT(Stride == 1);
return m_value->intVal;
}
bool asBool(void) const
{
DE_STATIC_ASSERT(Stride == 1);
return m_value->boolVal;
}
Scalar asScalar(void) const
{
DE_STATIC_ASSERT(Stride == 1);
return *m_value;
}
float asFloat(int ndx) const
{
DE_ASSERT(de::inBounds(ndx, 0, Stride));
return m_value[ndx].floatVal;
}
int asInt(int ndx) const
{
DE_ASSERT(de::inBounds(ndx, 0, Stride));
return m_value[ndx].intVal;
}
bool asBool(int ndx) const
{
DE_ASSERT(de::inBounds(ndx, 0, Stride));
return m_value[ndx].boolVal;
}
Scalar asScalar(int ndx) const
{
DE_ASSERT(de::inBounds(ndx, 0, Stride));
return m_value[ndx];
}
template <typename T>
T as(int ndx) const
{
DE_ASSERT(de::inBounds(ndx, 0, Stride));
return this->m_value[ndx].template as<T>();
}
// For assignment: b = a.value()
StridedValueRead<Stride> value(void) const
{
return StridedValueRead<Stride>(getType(), m_value);
}
protected:
const VariableType *m_type;
Scalar
*m_value; // \note Non-const internal pointer is used so that ValueAccess can extend this class with RW access
};
template <int Stride>
class StridedValueAccess : public ConstStridedValueAccess<Stride>
{
public:
StridedValueAccess(void)
{
}
StridedValueAccess(const VariableType &type, Scalar *valuePtr) : ConstStridedValueAccess<Stride>(type, valuePtr)
{
}
// Read-write access
StridedValueAccess component(int compNdx)
{
return StridedValueAccess(this->getType().getElementType(), this->m_value + Stride * compNdx);
}
StridedValueAccess arrayElement(int elementNdx)
{
return StridedValueAccess(this->getType().getElementType(),
this->m_value + Stride * this->getType().getElementScalarOffset(elementNdx));
}
StridedValueAccess member(int memberNdx)
{
return StridedValueAccess(this->getType().getMembers()[memberNdx].getType(),
this->m_value + Stride * this->getType().getMemberScalarOffset(memberNdx));
}
float &asFloat(void)
{
DE_STATIC_ASSERT(Stride == 1);
return this->m_value->floatVal;
}
int &asInt(void)
{
DE_STATIC_ASSERT(Stride == 1);
return this->m_value->intVal;
}
bool &asBool(void)
{
DE_STATIC_ASSERT(Stride == 1);
return this->m_value->boolVal;
}
Scalar &asScalar(void)
{
DE_STATIC_ASSERT(Stride == 1);
return *this->m_value;
}
float &asFloat(int ndx)
{
DE_ASSERT(de::inBounds(ndx, 0, Stride));
return this->m_value[ndx].floatVal;
}
int &asInt(int ndx)
{
DE_ASSERT(de::inBounds(ndx, 0, Stride));
return this->m_value[ndx].intVal;
}
bool &asBool(int ndx)
{
DE_ASSERT(de::inBounds(ndx, 0, Stride));
return this->m_value[ndx].boolVal;
}
Scalar &asScalar(int ndx)
{
DE_ASSERT(de::inBounds(ndx, 0, Stride));
return this->m_value[ndx];
}
template <typename T>
T &as(int ndx)
{
DE_ASSERT(de::inBounds(ndx, 0, Stride));
return this->m_value[ndx].template as<T>();
}
template <int SrcStride>
StridedValueAccess &operator=(const StridedValueRead<SrcStride> &value);
// Helpers, work only in Stride == 1 case
template <int Size>
StridedValueAccess &operator=(const tcu::Vector<float, Size> &vec);
StridedValueAccess &operator=(float floatVal)
{
asFloat() = floatVal;
return *this;
}
StridedValueAccess &operator=(int intVal)
{
asInt() = intVal;
return *this;
}
StridedValueAccess &operator=(bool boolVal)
{
asBool() = boolVal;
return *this;
}
StridedValueAccess &operator=(Scalar val)
{
asScalar() = val;
return *this;
}
};
template <int Stride>
template <int SrcStride>
StridedValueAccess<Stride> &StridedValueAccess<Stride>::operator=(const StridedValueRead<SrcStride> &valueRead)
{
DE_STATIC_ASSERT(SrcStride == Stride || SrcStride == 1);
DE_ASSERT(this->getType() == valueRead.getType());
int scalarSize = this->getType().getScalarSize();
if (scalarSize == 0)
return *this; // Happens when void value range is copied
if (Stride == SrcStride)
std::copy(valueRead.getValuePtr(), valueRead.getValuePtr() + scalarSize * Stride, this->m_value);
else
{
for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
std::fill(this->m_value + scalarNdx * Stride, this->m_value + (scalarNdx + 1) * Stride,
valueRead.getValuePtr()[scalarNdx]);
}
return *this;
}
template <int Stride>
template <int Size>
StridedValueAccess<Stride> &StridedValueAccess<Stride>::operator=(const tcu::Vector<float, Size> &vec)
{
DE_ASSERT(this->getType() == VariableType(VariableType::TYPE_FLOAT, Size));
for (int comp = 0; comp < 4; comp++)
component(comp).asFloat() = vec.getPtr()[comp];
return *this;
}
// Typedefs for stride == 1 case
typedef ConstStridedValueAccess<1> ConstValueAccess;
typedef StridedValueAccess<1> ValueAccess;
class ConstValueRangeAccess
{
public:
ConstValueRangeAccess(void) : m_type(DE_NULL), m_min(DE_NULL), m_max(DE_NULL)
{
}
ConstValueRangeAccess(const VariableType &type, const Scalar *minVal, const Scalar *maxVal)
: m_type(&type)
, m_min(const_cast<Scalar *>(minVal))
, m_max(const_cast<Scalar *>(maxVal))
{
}
const VariableType &getType(void) const
{
return *m_type;
}
ConstValueAccess getMin(void) const
{
return ConstValueAccess(*m_type, m_min);
}
ConstValueAccess getMax(void) const
{
return ConstValueAccess(*m_type, m_max);
}
// Read-only access
ConstValueRangeAccess component(int compNdx) const;
ConstValueRangeAccess arrayElement(int elementNdx) const;
ConstValueRangeAccess member(int memberNdx) const;
// Set operations - tests condition for all elements
bool intersects(const ConstValueRangeAccess &other) const;
bool isSupersetOf(const ConstValueRangeAccess &other) const;
bool isSubsetOf(const ConstValueRangeAccess &other) const;
protected:
const VariableType *m_type;
Scalar *m_min; // \note See note in ConstValueAccess
Scalar *m_max;
};
inline ConstValueRangeAccess ConstValueRangeAccess::component(int compNdx) const
{
return ConstValueRangeAccess(m_type->getElementType(), m_min + compNdx, m_max + compNdx);
}
inline ConstValueRangeAccess ConstValueRangeAccess::arrayElement(int elementNdx) const
{
int offset = m_type->getElementScalarOffset(elementNdx);
return ConstValueRangeAccess(m_type->getElementType(), m_min + offset, m_max + offset);
}
inline ConstValueRangeAccess ConstValueRangeAccess::member(int memberNdx) const
{
int offset = m_type->getMemberScalarOffset(memberNdx);
return ConstValueRangeAccess(m_type->getMembers()[memberNdx].getType(), m_min + offset, m_max + offset);
}
class ValueRangeAccess : public ConstValueRangeAccess
{
public:
ValueRangeAccess(const VariableType &type, Scalar *minVal, Scalar *maxVal)
: ConstValueRangeAccess(type, minVal, maxVal)
{
}
// Read-write access
ValueAccess getMin(void)
{
return ValueAccess(*m_type, m_min);
}
ValueAccess getMax(void)
{
return ValueAccess(*m_type, m_max);
}
ValueRangeAccess component(int compNdx);
ValueRangeAccess arrayElement(int elementNdx);
ValueRangeAccess member(int memberNdx);
};
inline ValueRangeAccess ValueRangeAccess::component(int compNdx)
{
return ValueRangeAccess(m_type->getElementType(), m_min + compNdx, m_max + compNdx);
}
inline ValueRangeAccess ValueRangeAccess::arrayElement(int elementNdx)
{
int offset = m_type->getElementScalarOffset(elementNdx);
return ValueRangeAccess(m_type->getElementType(), m_min + offset, m_max + offset);
}
inline ValueRangeAccess ValueRangeAccess::member(int memberNdx)
{
int offset = m_type->getMemberScalarOffset(memberNdx);
return ValueRangeAccess(m_type->getMembers()[memberNdx].getType(), m_min + offset, m_max + offset);
}
class ValueRange
{
public:
ValueRange(const VariableType &type);
ValueRange(const VariableType &type, const ConstValueAccess &minVal, const ConstValueAccess &maxVal);
ValueRange(const VariableType &type, const Scalar *minVal, const Scalar *maxVal);
ValueRange(ConstValueRangeAccess other);
~ValueRange(void);
const VariableType &getType(void) const
{
return m_type;
}
ValueAccess getMin(void)
{
return ValueAccess(m_type, getMinPtr());
}
ValueAccess getMax(void)
{
return ValueAccess(m_type, getMaxPtr());
}
ConstValueAccess getMin(void) const
{
return ConstValueAccess(m_type, getMinPtr());
}
ConstValueAccess getMax(void) const
{
return ConstValueAccess(m_type, getMaxPtr());
}
ValueRangeAccess asAccess(void)
{
return ValueRangeAccess(m_type, getMinPtr(), getMaxPtr());
}
ConstValueRangeAccess asAccess(void) const
{
return ConstValueRangeAccess(m_type, getMinPtr(), getMaxPtr());
}
operator ConstValueRangeAccess(void) const
{
return asAccess();
}
operator ValueRangeAccess(void)
{
return asAccess();
}
static void computeIntersection(ValueRangeAccess dst, const ConstValueRangeAccess &a,
const ConstValueRangeAccess &b);
static void computeIntersection(ValueRange &dst, const ConstValueRangeAccess &a, const ConstValueRangeAccess &b);
private:
const Scalar *getMinPtr(void) const
{
return m_min.empty() ? DE_NULL : &m_min[0];
}
const Scalar *getMaxPtr(void) const
{
return m_max.empty() ? DE_NULL : &m_max[0];
}
Scalar *getMinPtr(void)
{
return m_min.empty() ? DE_NULL : &m_min[0];
}
Scalar *getMaxPtr(void)
{
return m_max.empty() ? DE_NULL : &m_max[0];
}
VariableType m_type;
std::vector<Scalar> m_min;
std::vector<Scalar> m_max;
};
template <int Stride>
class ValueStorage
{
public:
ValueStorage(void);
ValueStorage(const VariableType &type);
void setStorage(const VariableType &type);
StridedValueAccess<Stride> getValue(const VariableType &type)
{
return StridedValueAccess<Stride>(type, &m_value[0]);
}
ConstStridedValueAccess<Stride> getValue(const VariableType &type) const
{
return ConstStridedValueAccess<Stride>(type, &m_value[0]);
}
private:
ValueStorage(const ValueStorage &other);
ValueStorage operator=(const ValueStorage &other);
std::vector<Scalar> m_value;
};
template <int Stride>
ValueStorage<Stride>::ValueStorage(void)
{
}
template <int Stride>
ValueStorage<Stride>::ValueStorage(const VariableType &type)
{
setStorage(type);
}
template <int Stride>
void ValueStorage<Stride>::setStorage(const VariableType &type)
{
m_value.resize(type.getScalarSize() * Stride);
}
class VariableValue
{
public:
VariableValue(const Variable *variable) : m_variable(variable), m_storage(m_variable->getType())
{
}
~VariableValue(void)
{
}
const Variable *getVariable(void) const
{
return m_variable;
}
ValueAccess getValue(void)
{
return m_storage.getValue(m_variable->getType());
}
ConstValueAccess getValue(void) const
{
return m_storage.getValue(m_variable->getType());
}
VariableValue(const VariableValue &other);
VariableValue &operator=(const VariableValue &other);
private:
const VariableType &getType(void) const
{
return m_variable->getType();
}
const Variable *m_variable;
ValueStorage<1> m_storage;
};
} // namespace rsg
#endif // _RSGVARIABLEVALUE_HPP