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
33namespace rsg
34{
35
36union Scalar
37{
38	int		intVal;
39	float	floatVal;
40	bool	boolVal;
41
42	Scalar (void)		: intVal	(0) {}
43	Scalar (float v)	: floatVal	(v) {}
44	Scalar (int v)		: intVal	(v) {}
45	Scalar (bool v)		: boolVal	(v) {}
46
47	// Bit-exact compare
48	bool operator== (Scalar other) const { return intVal == other.intVal; }
49	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};
57DE_STATIC_ASSERT(sizeof(Scalar) == sizeof(deUint32));
58
59template <> inline Scalar Scalar::min<float>	(void)	{ return Scalar((int)0xff800000);	}
60template <> inline Scalar Scalar::max<float>	(void)	{ return Scalar((int)0x7f800000);	}
61template <> inline Scalar Scalar::min<int>		(void)	{ return Scalar((int)0x80000000);	}
62template <> inline Scalar Scalar::max<int>		(void)	{ return Scalar((int)0x7fffffff);	}
63template <> inline Scalar Scalar::min<bool>		(void)	{ return Scalar(false);				}
64template <> inline Scalar Scalar::max<bool>		(void)	{ return Scalar(true);				}
65
66template <> inline float	Scalar::as<float>	(void) const	{ return floatVal;	}
67template <> inline float&	Scalar::as<float>	(void)			{ return floatVal;	}
68template <> inline int		Scalar::as<int>		(void) const	{ return intVal;	}
69template <> inline int&		Scalar::as<int>		(void)			{ return intVal;	}
70template <> inline bool		Scalar::as<bool>	(void) const	{ return boolVal;	}
71template <> inline bool&	Scalar::as<bool>	(void)			{ return boolVal;	}
72
73template <int Stride>
74class StridedValueRead
75{
76public:
77								StridedValueRead		(const VariableType& type, const Scalar* value) : m_type(type), m_value(value) {}
78
79	const VariableType&			getType					(void) const			{ return m_type;	}
80	const Scalar*				getValuePtr				(void) const			{ return m_value;	}
81
82private:
83	const VariableType&			m_type;
84	const Scalar*				m_value;
85};
86
87template <int Stride>
88class ConstStridedValueAccess
89{
90public:
91								ConstStridedValueAccess	(void) : m_type(DE_NULL), m_value(DE_NULL) {}
92								ConstStridedValueAccess	(const VariableType& type, const Scalar* valuePtr) : m_type(&type), m_value(const_cast<Scalar*>(valuePtr)) {}
93
94	const VariableType&			getType					(void) const			{ return *m_type;			}
95
96	// Read-only access
97	ConstStridedValueAccess		component				(int compNdx) const		{ return ConstStridedValueAccess(getType().getElementType(), m_value + Stride*compNdx);													}
98	ConstStridedValueAccess		arrayElement			(int elementNdx) const	{ return ConstStridedValueAccess(getType().getElementType(), m_value + Stride*getType().getElementScalarOffset(elementNdx));				}
99	ConstStridedValueAccess		member					(int memberNdx) const	{ return ConstStridedValueAccess(getType().getMembers()[memberNdx].getType(), m_value + Stride*getType().getMemberScalarOffset(memberNdx));	}
100
101	float						asFloat					(void) const			{ DE_STATIC_ASSERT(Stride == 1); return m_value->floatVal;	}
102	int							asInt					(void) const			{ DE_STATIC_ASSERT(Stride == 1); return m_value->intVal;	}
103	bool						asBool					(void) const			{ DE_STATIC_ASSERT(Stride == 1); return m_value->boolVal;	}
104	Scalar						asScalar				(void) const			{ DE_STATIC_ASSERT(Stride == 1); return *m_value;			}
105
106	float						asFloat					(int ndx) const			{ DE_ASSERT(de::inBounds(ndx, 0, Stride)); return m_value[ndx].floatVal;	}
107	int							asInt					(int ndx) const			{ DE_ASSERT(de::inBounds(ndx, 0, Stride)); return m_value[ndx].intVal;	}
108	bool						asBool					(int ndx) const			{ DE_ASSERT(de::inBounds(ndx, 0, Stride)); return m_value[ndx].boolVal;	}
109	Scalar						asScalar				(int ndx) const			{ DE_ASSERT(de::inBounds(ndx, 0, Stride)); return m_value[ndx];			}
110
111	template <typename T>
112	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()
115	StridedValueRead<Stride>	value					(void) const			{ return StridedValueRead<Stride>(getType(), m_value);		}
116
117protected:
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
122template <int Stride>
123class StridedValueAccess : public ConstStridedValueAccess<Stride>
124{
125public:
126								StridedValueAccess	(void) {}
127								StridedValueAccess	(const VariableType& type, Scalar* valuePtr) : ConstStridedValueAccess<Stride>(type, valuePtr) {}
128
129	// Read-write access
130	StridedValueAccess			component			(int compNdx)		{ return StridedValueAccess(this->getType().getElementType(), this->m_value + Stride*compNdx);													}
131	StridedValueAccess			arrayElement		(int elementNdx)	{ return StridedValueAccess(this->getType().getElementType(), this->m_value + Stride*this->getType().getElementScalarOffset(elementNdx));					}
132	StridedValueAccess			member				(int memberNdx)		{ return StridedValueAccess(this->getType().getMembers()[memberNdx].getType(), this->m_value + Stride*this->getType().getMemberScalarOffset(memberNdx));	}
133
134	float&						asFloat				(void)				{ DE_STATIC_ASSERT(Stride == 1); return this->m_value->floatVal;	}
135	int&						asInt				(void)				{ DE_STATIC_ASSERT(Stride == 1); return this->m_value->intVal;		}
136	bool&						asBool				(void)				{ DE_STATIC_ASSERT(Stride == 1); return this->m_value->boolVal;		}
137	Scalar&						asScalar			(void)				{ DE_STATIC_ASSERT(Stride == 1); return *this->m_value;				}
138
139	float&						asFloat				(int ndx)			{ DE_ASSERT(de::inBounds(ndx, 0, Stride)); return this->m_value[ndx].floatVal;	}
140	int&						asInt				(int ndx)			{ DE_ASSERT(de::inBounds(ndx, 0, Stride)); return this->m_value[ndx].intVal;		}
141	bool&						asBool				(int ndx)			{ DE_ASSERT(de::inBounds(ndx, 0, Stride)); return this->m_value[ndx].boolVal;		}
142	Scalar&						asScalar			(int ndx)			{ DE_ASSERT(de::inBounds(ndx, 0, Stride)); return this->m_value[ndx];				}
143
144	template <typename T>
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);
153	StridedValueAccess&			operator=			(float floatVal)	{ asFloat()		= floatVal;	return *this;	}
154	StridedValueAccess&			operator=			(int intVal)		{ asInt()		= intVal;	return *this;	}
155	StridedValueAccess&			operator=			(bool boolVal)		{ asBool()		= boolVal;	return *this;	}
156	StridedValueAccess&			operator=			(Scalar val)		{ asScalar()	= val;		return *this;	}
157};
158
159template <int Stride>
160template <int SrcStride>
161StridedValueAccess<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
182template <int Stride>
183template <int Size>
184StridedValueAccess<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
194typedef ConstStridedValueAccess<1>	ConstValueAccess;
195typedef StridedValueAccess<1>		ValueAccess;
196
197class ConstValueRangeAccess
198{
199public:
200								ConstValueRangeAccess	(void) : m_type(DE_NULL), m_min(DE_NULL), m_max(DE_NULL) {}
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
203	const VariableType&			getType					(void) const	{ return *m_type;							}
204	ConstValueAccess			getMin					(void) const	{ return ConstValueAccess(*m_type, m_min);	}
205	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
217protected:
218	const VariableType*			m_type;
219	Scalar*						m_min;	// \note See note in ConstValueAccess
220	Scalar*						m_max;
221};
222
223inline ConstValueRangeAccess ConstValueRangeAccess::component (int compNdx) const
224{
225	return ConstValueRangeAccess(m_type->getElementType(), m_min + compNdx, m_max + compNdx);
226}
227
228inline 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
234inline 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
240class ValueRangeAccess : public ConstValueRangeAccess
241{
242public:
243								ValueRangeAccess		(const VariableType& type, Scalar* minVal, Scalar* maxVal) : ConstValueRangeAccess(type, minVal, maxVal) {}
244
245	// Read-write access
246	ValueAccess					getMin					(void) { return ValueAccess(*m_type, m_min);	}
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
254inline ValueRangeAccess ValueRangeAccess::component (int compNdx)
255{
256	return ValueRangeAccess(m_type->getElementType(), m_min + compNdx, m_max + compNdx);
257}
258
259inline 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
265inline 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
271class ValueRange
272{
273public:
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
280	const VariableType&			getType				(void) const	{ return m_type;								}
281
282	ValueAccess					getMin				(void)			{ return ValueAccess(m_type, getMinPtr());		}
283	ValueAccess					getMax				(void)			{ return ValueAccess(m_type, getMaxPtr());		}
284
285	ConstValueAccess			getMin				(void) const	{ return ConstValueAccess(m_type, getMinPtr());	}
286	ConstValueAccess			getMax				(void) const	{ return ConstValueAccess(m_type, getMaxPtr());	}
287
288	ValueRangeAccess			asAccess			(void)			{ return ValueRangeAccess(m_type, getMinPtr(), getMaxPtr());		}
289	ConstValueRangeAccess		asAccess			(void) const	{ return ConstValueRangeAccess(m_type, getMinPtr(), getMaxPtr());	}
290
291	operator ConstValueRangeAccess					(void) const	{ return asAccess();							}
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
297private:
298	const Scalar*				getMinPtr			(void) const	{ return m_min.empty() ? DE_NULL : &m_min[0];	}
299	const Scalar*				getMaxPtr			(void) const	{ return m_max.empty() ? DE_NULL : &m_max[0];	}
300
301	Scalar*						getMinPtr			(void)			{ return m_min.empty() ? DE_NULL : &m_min[0];	}
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
309template <int Stride>
310class ValueStorage
311{
312public:
313										ValueStorage		(void);
314										ValueStorage		(const VariableType& type);
315
316	void								setStorage			(const VariableType& type);
317
318	StridedValueAccess<Stride>			getValue			(const VariableType& type)			{ return StridedValueAccess<Stride>(type, &m_value[0]);			}
319	ConstStridedValueAccess<Stride>		getValue			(const VariableType& type) const	{ return ConstStridedValueAccess<Stride>(type, &m_value[0]);	}
320
321private:
322										ValueStorage		(const ValueStorage& other);
323	ValueStorage						operator=			(const ValueStorage& other);
324
325	std::vector<Scalar>					m_value;
326};
327
328template <int Stride>
329ValueStorage<Stride>::ValueStorage (void)
330{
331}
332
333template <int Stride>
334ValueStorage<Stride>::ValueStorage (const VariableType& type)
335{
336	setStorage(type);
337}
338
339template <int Stride>
340void ValueStorage<Stride>::setStorage (const VariableType& type)
341{
342	m_value.resize(type.getScalarSize() * Stride);
343}
344
345class VariableValue
346{
347public:
348							VariableValue		(const Variable* variable) : m_variable(variable), m_storage(m_variable->getType()) {}
349							~VariableValue		(void) {}
350
351	const Variable*			getVariable			(void) const	{ return m_variable;								}
352	ValueAccess				getValue			(void)			{ return m_storage.getValue(m_variable->getType());	}
353	ConstValueAccess		getValue			(void) const	{ return m_storage.getValue(m_variable->getType());	}
354
355							VariableValue		(const VariableValue& other);
356	VariableValue&			operator=			(const VariableValue& other);
357
358private:
359	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