1 #ifndef _RSGVARIABLEVALUE_HPP
2 #define _RSGVARIABLEVALUE_HPP
3 /*-------------------------------------------------------------------------
4 * drawElements Quality Program Random Shader Generator
5 * ----------------------------------------------------
6 *
7 * Copyright 2014 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Variable Value class.
24 *//*--------------------------------------------------------------------*/
25
26 #include "rsgDefs.hpp"
27 #include "rsgVariableType.hpp"
28 #include "rsgVariable.hpp"
29 #include "tcuVector.hpp"
30
31 #include <algorithm>
32
33 namespace rsg
34 {
35
36 union Scalar
37 {
38 int intVal;
39 float floatVal;
40 bool boolVal;
41
Scalar(void)42 Scalar (void) : intVal (0) {}
Scalar(float v)43 Scalar (float v) : floatVal (v) {}
Scalar(int v)44 Scalar (int v) : intVal (v) {}
Scalar(bool v)45 Scalar (bool v) : boolVal (v) {}
46
47 // Bit-exact compare
operator ==(Scalar other) const48 bool operator== (Scalar other) const { return intVal == other.intVal; }
operator !=(Scalar other) const49 bool operator!= (Scalar other) const { return intVal != other.intVal; }
50
51 template <typename T> static Scalar min (void);
52 template <typename T> static Scalar max (void);
53
54 template <typename T> T as (void) const;
55 template <typename T> T& as (void);
56 };
57 DE_STATIC_ASSERT(sizeof(Scalar) == sizeof(deUint32));
58
min(void)59 template <> inline Scalar Scalar::min<float> (void) { return Scalar((int)0xff800000); }
max(void)60 template <> inline Scalar Scalar::max<float> (void) { return Scalar((int)0x7f800000); }
min(void)61 template <> inline Scalar Scalar::min<int> (void) { return Scalar((int)0x80000000); }
max(void)62 template <> inline Scalar Scalar::max<int> (void) { return Scalar((int)0x7fffffff); }
min(void)63 template <> inline Scalar Scalar::min<bool> (void) { return Scalar(false); }
max(void)64 template <> inline Scalar Scalar::max<bool> (void) { return Scalar(true); }
65
as(void) const66 template <> inline float Scalar::as<float> (void) const { return floatVal; }
as(void)67 template <> inline float& Scalar::as<float> (void) { return floatVal; }
as(void) const68 template <> inline int Scalar::as<int> (void) const { return intVal; }
as(void)69 template <> inline int& Scalar::as<int> (void) { return intVal; }
as(void) const70 template <> inline bool Scalar::as<bool> (void) const { return boolVal; }
as(void)71 template <> inline bool& Scalar::as<bool> (void) { return boolVal; }
72
73 template <int Stride>
74 class StridedValueRead
75 {
76 public:
StridedValueRead(const VariableType & type,const Scalar * value)77 StridedValueRead (const VariableType& type, const Scalar* value) : m_type(type), m_value(value) {}
78
getType(void) const79 const VariableType& getType (void) const { return m_type; }
getValuePtr(void) const80 const Scalar* getValuePtr (void) const { return m_value; }
81
82 private:
83 const VariableType& m_type;
84 const Scalar* m_value;
85 };
86
87 template <int Stride>
88 class ConstStridedValueAccess
89 {
90 public:
ConstStridedValueAccess(void)91 ConstStridedValueAccess (void) : m_type(DE_NULL), m_value(DE_NULL) {}
ConstStridedValueAccess(const VariableType & type,const Scalar * valuePtr)92 ConstStridedValueAccess (const VariableType& type, const Scalar* valuePtr) : m_type(&type), m_value(const_cast<Scalar*>(valuePtr)) {}
93
getType(void) const94 const VariableType& getType (void) const { return *m_type; }
95
96 // Read-only access
component(int compNdx) const97 ConstStridedValueAccess component (int compNdx) const { return ConstStridedValueAccess(getType().getElementType(), m_value + Stride*compNdx); }
arrayElement(int elementNdx) const98 ConstStridedValueAccess arrayElement (int elementNdx) const { return ConstStridedValueAccess(getType().getElementType(), m_value + Stride*getType().getElementScalarOffset(elementNdx)); }
member(int memberNdx) const99 ConstStridedValueAccess member (int memberNdx) const { return ConstStridedValueAccess(getType().getMembers()[memberNdx].getType(), m_value + Stride*getType().getMemberScalarOffset(memberNdx)); }
100
asFloat(void) const101 float asFloat (void) const { DE_STATIC_ASSERT(Stride == 1); return m_value->floatVal; }
asInt(void) const102 int asInt (void) const { DE_STATIC_ASSERT(Stride == 1); return m_value->intVal; }
asBool(void) const103 bool asBool (void) const { DE_STATIC_ASSERT(Stride == 1); return m_value->boolVal; }
asScalar(void) const104 Scalar asScalar (void) const { DE_STATIC_ASSERT(Stride == 1); return *m_value; }
105
asFloat(int ndx) const106 float asFloat (int ndx) const { DE_ASSERT(de::inBounds(ndx, 0, Stride)); return m_value[ndx].floatVal; }
asInt(int ndx) const107 int asInt (int ndx) const { DE_ASSERT(de::inBounds(ndx, 0, Stride)); return m_value[ndx].intVal; }
asBool(int ndx) const108 bool asBool (int ndx) const { DE_ASSERT(de::inBounds(ndx, 0, Stride)); return m_value[ndx].boolVal; }
asScalar(int ndx) const109 Scalar asScalar (int ndx) const { DE_ASSERT(de::inBounds(ndx, 0, Stride)); return m_value[ndx]; }
110
111 template <typename T>
as(int ndx) const112 T as (int ndx) const { DE_ASSERT(de::inBounds(ndx, 0, Stride)); return this->m_value[ndx].template as<T>(); }
113
114 // For assignment: b = a.value()
value(void) const115 StridedValueRead<Stride> value (void) const { return StridedValueRead<Stride>(getType(), m_value); }
116
117 protected:
118 const VariableType* m_type;
119 Scalar* m_value; // \note Non-const internal pointer is used so that ValueAccess can extend this class with RW access
120 };
121
122 template <int Stride>
123 class StridedValueAccess : public ConstStridedValueAccess<Stride>
124 {
125 public:
StridedValueAccess(void)126 StridedValueAccess (void) {}
StridedValueAccess(const VariableType & type,Scalar * valuePtr)127 StridedValueAccess (const VariableType& type, Scalar* valuePtr) : ConstStridedValueAccess<Stride>(type, valuePtr) {}
128
129 // Read-write access
component(int compNdx)130 StridedValueAccess component (int compNdx) { return StridedValueAccess(this->getType().getElementType(), this->m_value + Stride*compNdx); }
arrayElement(int elementNdx)131 StridedValueAccess arrayElement (int elementNdx) { return StridedValueAccess(this->getType().getElementType(), this->m_value + Stride*this->getType().getElementScalarOffset(elementNdx)); }
member(int memberNdx)132 StridedValueAccess member (int memberNdx) { return StridedValueAccess(this->getType().getMembers()[memberNdx].getType(), this->m_value + Stride*this->getType().getMemberScalarOffset(memberNdx)); }
133
asFloat(void)134 float& asFloat (void) { DE_STATIC_ASSERT(Stride == 1); return this->m_value->floatVal; }
asInt(void)135 int& asInt (void) { DE_STATIC_ASSERT(Stride == 1); return this->m_value->intVal; }
asBool(void)136 bool& asBool (void) { DE_STATIC_ASSERT(Stride == 1); return this->m_value->boolVal; }
asScalar(void)137 Scalar& asScalar (void) { DE_STATIC_ASSERT(Stride == 1); return *this->m_value; }
138
asFloat(int ndx)139 float& asFloat (int ndx) { DE_ASSERT(de::inBounds(ndx, 0, Stride)); return this->m_value[ndx].floatVal; }
asInt(int ndx)140 int& asInt (int ndx) { DE_ASSERT(de::inBounds(ndx, 0, Stride)); return this->m_value[ndx].intVal; }
asBool(int ndx)141 bool& asBool (int ndx) { DE_ASSERT(de::inBounds(ndx, 0, Stride)); return this->m_value[ndx].boolVal; }
asScalar(int ndx)142 Scalar& asScalar (int ndx) { DE_ASSERT(de::inBounds(ndx, 0, Stride)); return this->m_value[ndx]; }
143
144 template <typename T>
as(int ndx)145 T& as (int ndx) { DE_ASSERT(de::inBounds(ndx, 0, Stride)); return this->m_value[ndx].template as<T>(); }
146
147 template <int SrcStride>
148 StridedValueAccess& operator= (const StridedValueRead<SrcStride>& value);
149
150 // Helpers, work only in Stride == 1 case
151 template <int Size>
152 StridedValueAccess& operator= (const tcu::Vector<float, Size>& vec);
operator =(float floatVal)153 StridedValueAccess& operator= (float floatVal) { asFloat() = floatVal; return *this; }
operator =(int intVal)154 StridedValueAccess& operator= (int intVal) { asInt() = intVal; return *this; }
operator =(bool boolVal)155 StridedValueAccess& operator= (bool boolVal) { asBool() = boolVal; return *this; }
operator =(Scalar val)156 StridedValueAccess& operator= (Scalar val) { asScalar() = val; return *this; }
157 };
158
159 template <int Stride>
160 template <int SrcStride>
operator =(const StridedValueRead<SrcStride> & valueRead)161 StridedValueAccess<Stride>& StridedValueAccess<Stride>::operator= (const StridedValueRead<SrcStride>& valueRead)
162 {
163 DE_STATIC_ASSERT(SrcStride == Stride || SrcStride == 1);
164 DE_ASSERT(this->getType() == valueRead.getType());
165
166 int scalarSize = this->getType().getScalarSize();
167
168 if (scalarSize == 0)
169 return *this; // Happens when void value range is copied
170
171 if (Stride == SrcStride)
172 std::copy(valueRead.getValuePtr(), valueRead.getValuePtr() + scalarSize*Stride, this->m_value);
173 else
174 {
175 for (int scalarNdx = 0; scalarNdx < scalarSize; scalarNdx++)
176 std::fill(this->m_value + scalarNdx*Stride, this->m_value + (scalarNdx+1)*Stride, valueRead.getValuePtr()[scalarNdx]);
177 }
178
179 return *this;
180 }
181
182 template <int Stride>
183 template <int Size>
operator =(const tcu::Vector<float,Size> & vec)184 StridedValueAccess<Stride>& StridedValueAccess<Stride>::operator= (const tcu::Vector<float, Size>& vec)
185 {
186 DE_ASSERT(this->getType() == VariableType(VariableType::TYPE_FLOAT, Size));
187 for (int comp = 0; comp < 4; comp++)
188 component(comp).asFloat() = vec.getPtr()[comp];
189
190 return *this;
191 }
192
193 // Typedefs for stride == 1 case
194 typedef ConstStridedValueAccess<1> ConstValueAccess;
195 typedef StridedValueAccess<1> ValueAccess;
196
197 class ConstValueRangeAccess
198 {
199 public:
ConstValueRangeAccess(void)200 ConstValueRangeAccess (void) : m_type(DE_NULL), m_min(DE_NULL), m_max(DE_NULL) {}
ConstValueRangeAccess(const VariableType & type,const Scalar * minVal,const Scalar * maxVal)201 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)) {}
202
getType(void) const203 const VariableType& getType (void) const { return *m_type; }
getMin(void) const204 ConstValueAccess getMin (void) const { return ConstValueAccess(*m_type, m_min); }
getMax(void) const205 ConstValueAccess getMax (void) const { return ConstValueAccess(*m_type, m_max); }
206
207 // Read-only access
208 ConstValueRangeAccess component (int compNdx) const;
209 ConstValueRangeAccess arrayElement (int elementNdx) const;
210 ConstValueRangeAccess member (int memberNdx) const;
211
212 // Set operations - tests condition for all elements
213 bool intersects (const ConstValueRangeAccess& other) const;
214 bool isSupersetOf (const ConstValueRangeAccess& other) const;
215 bool isSubsetOf (const ConstValueRangeAccess& other) const;
216
217 protected:
218 const VariableType* m_type;
219 Scalar* m_min; // \note See note in ConstValueAccess
220 Scalar* m_max;
221 };
222
component(int compNdx) const223 inline ConstValueRangeAccess ConstValueRangeAccess::component (int compNdx) const
224 {
225 return ConstValueRangeAccess(m_type->getElementType(), m_min + compNdx, m_max + compNdx);
226 }
227
arrayElement(int elementNdx) const228 inline ConstValueRangeAccess ConstValueRangeAccess::arrayElement (int elementNdx) const
229 {
230 int offset = m_type->getElementScalarOffset(elementNdx);
231 return ConstValueRangeAccess(m_type->getElementType(), m_min + offset, m_max + offset);
232 }
233
member(int memberNdx) const234 inline ConstValueRangeAccess ConstValueRangeAccess::member (int memberNdx) const
235 {
236 int offset = m_type->getMemberScalarOffset(memberNdx);
237 return ConstValueRangeAccess(m_type->getMembers()[memberNdx].getType(), m_min + offset, m_max + offset);
238 }
239
240 class ValueRangeAccess : public ConstValueRangeAccess
241 {
242 public:
ValueRangeAccess(const VariableType & type,Scalar * minVal,Scalar * maxVal)243 ValueRangeAccess (const VariableType& type, Scalar* minVal, Scalar* maxVal) : ConstValueRangeAccess(type, minVal, maxVal) {}
244
245 // Read-write access
getMin(void)246 ValueAccess getMin (void) { return ValueAccess(*m_type, m_min); }
getMax(void)247 ValueAccess getMax (void) { return ValueAccess(*m_type, m_max); }
248
249 ValueRangeAccess component (int compNdx);
250 ValueRangeAccess arrayElement (int elementNdx);
251 ValueRangeAccess member (int memberNdx);
252 };
253
component(int compNdx)254 inline ValueRangeAccess ValueRangeAccess::component (int compNdx)
255 {
256 return ValueRangeAccess(m_type->getElementType(), m_min + compNdx, m_max + compNdx);
257 }
258
arrayElement(int elementNdx)259 inline ValueRangeAccess ValueRangeAccess::arrayElement (int elementNdx)
260 {
261 int offset = m_type->getElementScalarOffset(elementNdx);
262 return ValueRangeAccess(m_type->getElementType(), m_min + offset, m_max + offset);
263 }
264
member(int memberNdx)265 inline ValueRangeAccess ValueRangeAccess::member (int memberNdx)
266 {
267 int offset = m_type->getMemberScalarOffset(memberNdx);
268 return ValueRangeAccess(m_type->getMembers()[memberNdx].getType(), m_min + offset, m_max + offset);
269 }
270
271 class ValueRange
272 {
273 public:
274 ValueRange (const VariableType& type);
275 ValueRange (const VariableType& type, const ConstValueAccess& minVal, const ConstValueAccess& maxVal);
276 ValueRange (const VariableType& type, const Scalar* minVal, const Scalar* maxVal);
277 ValueRange (ConstValueRangeAccess other);
278 ~ValueRange (void);
279
getType(void) const280 const VariableType& getType (void) const { return m_type; }
281
getMin(void)282 ValueAccess getMin (void) { return ValueAccess(m_type, getMinPtr()); }
getMax(void)283 ValueAccess getMax (void) { return ValueAccess(m_type, getMaxPtr()); }
284
getMin(void) const285 ConstValueAccess getMin (void) const { return ConstValueAccess(m_type, getMinPtr()); }
getMax(void) const286 ConstValueAccess getMax (void) const { return ConstValueAccess(m_type, getMaxPtr()); }
287
asAccess(void)288 ValueRangeAccess asAccess (void) { return ValueRangeAccess(m_type, getMinPtr(), getMaxPtr()); }
asAccess(void) const289 ConstValueRangeAccess asAccess (void) const { return ConstValueRangeAccess(m_type, getMinPtr(), getMaxPtr()); }
290
operator ConstValueRangeAccess(void) const291 operator ConstValueRangeAccess (void) const { return asAccess(); }
operator ValueRangeAccess(void)292 operator ValueRangeAccess (void) { return asAccess(); }
293
294 static void computeIntersection (ValueRangeAccess dst, const ConstValueRangeAccess& a, const ConstValueRangeAccess& b);
295 static void computeIntersection (ValueRange& dst, const ConstValueRangeAccess& a, const ConstValueRangeAccess& b);
296
297 private:
getMinPtr(void) const298 const Scalar* getMinPtr (void) const { return m_min.empty() ? DE_NULL : &m_min[0]; }
getMaxPtr(void) const299 const Scalar* getMaxPtr (void) const { return m_max.empty() ? DE_NULL : &m_max[0]; }
300
getMinPtr(void)301 Scalar* getMinPtr (void) { return m_min.empty() ? DE_NULL : &m_min[0]; }
getMaxPtr(void)302 Scalar* getMaxPtr (void) { return m_max.empty() ? DE_NULL : &m_max[0]; }
303
304 VariableType m_type;
305 std::vector<Scalar> m_min;
306 std::vector<Scalar> m_max;
307 };
308
309 template <int Stride>
310 class ValueStorage
311 {
312 public:
313 ValueStorage (void);
314 ValueStorage (const VariableType& type);
315
316 void setStorage (const VariableType& type);
317
getValue(const VariableType & type)318 StridedValueAccess<Stride> getValue (const VariableType& type) { return StridedValueAccess<Stride>(type, &m_value[0]); }
getValue(const VariableType & type) const319 ConstStridedValueAccess<Stride> getValue (const VariableType& type) const { return ConstStridedValueAccess<Stride>(type, &m_value[0]); }
320
321 private:
322 ValueStorage (const ValueStorage& other);
323 ValueStorage operator= (const ValueStorage& other);
324
325 std::vector<Scalar> m_value;
326 };
327
328 template <int Stride>
ValueStorage(void)329 ValueStorage<Stride>::ValueStorage (void)
330 {
331 }
332
333 template <int Stride>
ValueStorage(const VariableType & type)334 ValueStorage<Stride>::ValueStorage (const VariableType& type)
335 {
336 setStorage(type);
337 }
338
339 template <int Stride>
setStorage(const VariableType & type)340 void ValueStorage<Stride>::setStorage (const VariableType& type)
341 {
342 m_value.resize(type.getScalarSize() * Stride);
343 }
344
345 class VariableValue
346 {
347 public:
VariableValue(const Variable * variable)348 VariableValue (const Variable* variable) : m_variable(variable), m_storage(m_variable->getType()) {}
~VariableValue(void)349 ~VariableValue (void) {}
350
getVariable(void) const351 const Variable* getVariable (void) const { return m_variable; }
getValue(void)352 ValueAccess getValue (void) { return m_storage.getValue(m_variable->getType()); }
getValue(void) const353 ConstValueAccess getValue (void) const { return m_storage.getValue(m_variable->getType()); }
354
355 VariableValue (const VariableValue& other);
356 VariableValue& operator= (const VariableValue& other);
357
358 private:
getType(void) const359 const VariableType& getType (void) const { return m_variable->getType(); }
360
361 const Variable* m_variable;
362 ValueStorage<1> m_storage;
363 };
364
365 } // rsg
366
367 #endif // _RSGVARIABLEVALUE_HPP
368