1#ifndef _GLSSHADERRENDERCASE_HPP
2#define _GLSSHADERRENDERCASE_HPP
3/*-------------------------------------------------------------------------
4 * drawElements Quality Program OpenGL (ES) Module
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 Shader execute test.
24 *//*--------------------------------------------------------------------*/
25
26#include "tcuDefs.hpp"
27#include "tcuTestCase.hpp"
28#include "tcuVector.hpp"
29#include "tcuMatrix.hpp"
30#include "tcuTexture.hpp"
31#include "tcuSurface.hpp"
32#include "gluRenderContext.hpp"
33#include "gluContextInfo.hpp"
34#include "gluShaderProgram.hpp"
35
36#include <sstream>
37#include <string>
38
39namespace glu
40{
41class RenderContext;
42class Texture2D;
43class TextureCube;
44class Texture2DArray;
45class Texture3D;
46} // glu
47
48namespace deqp
49{
50namespace gls
51{
52
53// LineStream \todo [2011-10-17 pyry] Move to proper place!
54
55class LineStream
56{
57public:
58						LineStream		(int indent = 0)	{ m_indent = indent; }
59						~LineStream		(void)				{}
60
61	const char*			str				(void) const		{ m_string = m_stream.str(); return m_string.c_str(); }
62	LineStream&			operator<<		(const char* line)	{ for (int i = 0; i < m_indent; i++) { m_stream << "\t"; } m_stream << line << "\n"; return *this; }
63
64private:
65	int					m_indent;
66	std::ostringstream	m_stream;
67	mutable std::string	m_string;
68};
69
70class QuadGrid;
71
72// TextureBinding
73
74class TextureBinding
75{
76public:
77	enum Type
78	{
79		TYPE_NONE = 0,
80		TYPE_2D,
81		TYPE_CUBE_MAP,
82		TYPE_2D_ARRAY,
83		TYPE_3D,
84
85		TYPE_LAST
86	};
87
88								TextureBinding		(const glu::Texture2D* tex2D, const tcu::Sampler& sampler);
89								TextureBinding		(const glu::TextureCube* texCube, const tcu::Sampler& sampler);
90								TextureBinding		(const glu::Texture2DArray* tex2DArray, const tcu::Sampler& sampler);
91								TextureBinding		(const glu::Texture3D* tex3D, const tcu::Sampler& sampler);
92								TextureBinding		(void);
93
94	void						setSampler			(const tcu::Sampler& sampler);
95	void						setTexture			(const glu::Texture2D* tex2D);
96	void						setTexture			(const glu::TextureCube* texCube);
97	void						setTexture			(const glu::Texture2DArray* tex2DArray);
98	void						setTexture			(const glu::Texture3D* tex3D);
99
100	Type						getType				(void) const { return m_type;		}
101	const tcu::Sampler&			getSampler			(void) const { return m_sampler;	}
102	const glu::Texture2D*		get2D				(void) const { DE_ASSERT(getType() == TYPE_2D);			return m_binding.tex2D;		}
103	const glu::TextureCube*		getCube				(void) const { DE_ASSERT(getType() == TYPE_CUBE_MAP);	return m_binding.texCube;	}
104	const glu::Texture2DArray*	get2DArray			(void) const { DE_ASSERT(getType() == TYPE_2D_ARRAY);	return m_binding.tex2DArray;}
105	const glu::Texture3D*		get3D				(void) const { DE_ASSERT(getType() == TYPE_3D);			return m_binding.tex3D;		}
106
107private:
108	Type					m_type;
109	tcu::Sampler			m_sampler;
110	union
111	{
112		const glu::Texture2D*		tex2D;
113		const glu::TextureCube*		texCube;
114		const glu::Texture2DArray*	tex2DArray;
115		const glu::Texture3D*		tex3D;
116	} m_binding;
117};
118
119// ShaderEvalContext.
120
121class ShaderEvalContext
122{
123public:
124	// Limits.
125	enum
126	{
127		MAX_USER_ATTRIBS	= 4,
128		MAX_TEXTURES		= 4,
129	};
130
131	struct ShaderSampler
132	{
133		tcu::Sampler				sampler;
134		const tcu::Texture2D*		tex2D;
135		const tcu::TextureCube*		texCube;
136		const tcu::Texture2DArray*	tex2DArray;
137		const tcu::Texture3D*		tex3D;
138
139		inline ShaderSampler (void)
140			: tex2D		(DE_NULL)
141			, texCube	(DE_NULL)
142			, tex2DArray(DE_NULL)
143			, tex3D		(DE_NULL)
144		{
145		}
146	};
147
148							ShaderEvalContext		(const QuadGrid& quadGrid);
149							~ShaderEvalContext		(void);
150
151	void					reset					(float sx, float sy);
152
153	// Inputs.
154	tcu::Vec4				coords;
155	tcu::Vec4				unitCoords;
156	tcu::Vec4				constCoords;
157
158	tcu::Vec4				in[MAX_USER_ATTRIBS];
159	ShaderSampler			textures[MAX_TEXTURES];
160
161	// Output.
162	tcu::Vec4				color;
163	bool					isDiscarded;
164
165	// Functions.
166	inline void				discard					(void)	{ isDiscarded = true; }
167	tcu::Vec4				texture2D				(int unitNdx, const tcu::Vec2& coords);
168
169private:
170	const QuadGrid&			quadGrid;
171};
172
173// ShaderEvalFunc.
174
175typedef void (*ShaderEvalFunc) (ShaderEvalContext& c);
176
177inline void evalCoordsPassthroughX		(ShaderEvalContext& c) { c.color.x() = c.coords.x(); }
178inline void evalCoordsPassthroughXY		(ShaderEvalContext& c) { c.color.xy() = c.coords.swizzle(0,1); }
179inline void evalCoordsPassthroughXYZ	(ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(0,1,2); }
180inline void evalCoordsPassthrough		(ShaderEvalContext& c) { c.color = c.coords; }
181inline void evalCoordsSwizzleWZYX		(ShaderEvalContext& c) { c.color = c.coords.swizzle(3,2,1,0); }
182
183// ShaderEvaluator
184// Either inherit a class with overridden evaluate() or just pass in an evalFunc.
185
186class ShaderEvaluator
187{
188public:
189						ShaderEvaluator			(void);
190						ShaderEvaluator			(ShaderEvalFunc evalFunc);
191	virtual				~ShaderEvaluator		(void);
192
193	virtual void		evaluate				(ShaderEvalContext& ctx);
194
195private:
196						ShaderEvaluator			(const ShaderEvaluator&);	// not allowed!
197	ShaderEvaluator&	operator=				(const ShaderEvaluator&);	// not allowed!
198
199	ShaderEvalFunc		m_evalFunc;
200};
201
202// ShaderRenderCase.
203
204class ShaderRenderCase : public tcu::TestCase
205{
206public:
207								ShaderRenderCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* description, bool isVertexCase, ShaderEvalFunc evalFunc);
208								ShaderRenderCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, const char* name, const char* description, bool isVertexCase, ShaderEvaluator& evaluator);
209	virtual						~ShaderRenderCase		(void);
210
211	void						init					(void);
212	void						deinit					(void);
213
214	IterateResult				iterate					(void);
215
216protected:
217	virtual void				setupShaderData			(void);
218	virtual void				setup					(int programID);
219	virtual void				setupUniforms			(int programID, const tcu::Vec4& constCoords);
220
221	tcu::IVec2					getViewportSize			(void) const;
222
223	class CompileFailed : public tcu::TestError
224	{
225	public:
226		inline CompileFailed (const char* file, int line) : tcu::TestError("Failed to compile shader program", DE_NULL, file, line) {}
227	};
228
229private:
230								ShaderRenderCase		(const ShaderRenderCase&);		// not allowed!
231	ShaderRenderCase&			operator=				(const ShaderRenderCase&);		// not allowed!
232
233	void						setupDefaultInputs		(int programID);
234
235	void						render					(tcu::Surface& result, int programID, const QuadGrid& quadGrid);
236	void						computeVertexReference	(tcu::Surface& result, const QuadGrid& quadGrid);
237	void						computeFragmentReference(tcu::Surface& result, const QuadGrid& quadGrid);
238	bool						compareImages			(const tcu::Surface& resImage, const tcu::Surface& refImage, float errorThreshold);
239
240protected:
241	glu::RenderContext&			m_renderCtx;
242	const glu::ContextInfo&		m_ctxInfo;
243
244	bool						m_isVertexCase;
245	ShaderEvaluator				m_defaultEvaluator;
246	ShaderEvaluator&			m_evaluator;
247	std::string					m_vertShaderSource;
248	std::string					m_fragShaderSource;
249	tcu::Vec4					m_clearColor;
250
251	std::vector<tcu::Mat4>		m_userAttribTransforms;
252	std::vector<TextureBinding>	m_textures;
253
254	glu::ShaderProgram*			m_program;
255};
256
257// Helpers.
258// \todo [2012-04-10 pyry] Move these to separate utility?
259
260const char*		getIntUniformName			(int number);
261const char*		getFloatUniformName			(int number);
262const char*		getFloatFractionUniformName	(int number);
263
264void			setupDefaultUniforms		(const glu::RenderContext& context, deUint32 programID);
265
266} // gls
267} // deqp
268
269#endif // _GLSSHADERRENDERCASE_HPP
270