You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
368 lines
15 KiB
368 lines
15 KiB
#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
|