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