| #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(deUint32)); |
| |
| 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; |
| }; |
| |
| } // rsg |
| |
| #endif // _RSGVARIABLEVALUE_HPP |