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 
39 namespace glu
40 {
41 class RenderContext;
42 class Texture2D;
43 class TextureCube;
44 class Texture2DArray;
45 class Texture3D;
46 } // glu
47 
48 namespace deqp
49 {
50 namespace gls
51 {
52 
53 // LineStream \todo [2011-10-17 pyry] Move to proper place!
54 
55 class LineStream
56 {
57 public:
LineStream(int indent=0)58 						LineStream		(int indent = 0)	{ m_indent = indent; }
~LineStream(void)59 						~LineStream		(void)				{}
60 
str(void) const61 	const char*			str				(void) const		{ m_string = m_stream.str(); return m_string.c_str(); }
operator <<(const char * line)62 	LineStream&			operator<<		(const char* line)	{ for (int i = 0; i < m_indent; i++) { m_stream << "\t"; } m_stream << line << "\n"; return *this; }
63 
64 private:
65 	int					m_indent;
66 	std::ostringstream	m_stream;
67 	mutable std::string	m_string;
68 };
69 
70 class QuadGrid;
71 
72 // TextureBinding
73 
74 class TextureBinding
75 {
76 public:
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 
getType(void) const100 	Type						getType				(void) const { return m_type;		}
getSampler(void) const101 	const tcu::Sampler&			getSampler			(void) const { return m_sampler;	}
get2D(void) const102 	const glu::Texture2D*		get2D				(void) const { DE_ASSERT(getType() == TYPE_2D);			return m_binding.tex2D;		}
getCube(void) const103 	const glu::TextureCube*		getCube				(void) const { DE_ASSERT(getType() == TYPE_CUBE_MAP);	return m_binding.texCube;	}
get2DArray(void) const104 	const glu::Texture2DArray*	get2DArray			(void) const { DE_ASSERT(getType() == TYPE_2D_ARRAY);	return m_binding.tex2DArray;}
get3D(void) const105 	const glu::Texture3D*		get3D				(void) const { DE_ASSERT(getType() == TYPE_3D);			return m_binding.tex3D;		}
106 
107 private:
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 
121 class ShaderEvalContext
122 {
123 public:
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 
ShaderSamplerdeqp::gls::ShaderEvalContext::ShaderSampler139 		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.
discard(void)166 	inline void				discard					(void)	{ isDiscarded = true; }
167 	tcu::Vec4				texture2D				(int unitNdx, const tcu::Vec2& coords);
168 
169 private:
170 	const QuadGrid&			quadGrid;
171 };
172 
173 // ShaderEvalFunc.
174 
175 typedef void (*ShaderEvalFunc) (ShaderEvalContext& c);
176 
evalCoordsPassthroughX(ShaderEvalContext & c)177 inline void evalCoordsPassthroughX		(ShaderEvalContext& c) { c.color.x() = c.coords.x(); }
evalCoordsPassthroughXY(ShaderEvalContext & c)178 inline void evalCoordsPassthroughXY		(ShaderEvalContext& c) { c.color.xy() = c.coords.swizzle(0,1); }
evalCoordsPassthroughXYZ(ShaderEvalContext & c)179 inline void evalCoordsPassthroughXYZ	(ShaderEvalContext& c) { c.color.xyz() = c.coords.swizzle(0,1,2); }
evalCoordsPassthrough(ShaderEvalContext & c)180 inline void evalCoordsPassthrough		(ShaderEvalContext& c) { c.color = c.coords; }
evalCoordsSwizzleWZYX(ShaderEvalContext & c)181 inline 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 
186 class ShaderEvaluator
187 {
188 public:
189 						ShaderEvaluator			(void);
190 						ShaderEvaluator			(ShaderEvalFunc evalFunc);
191 	virtual				~ShaderEvaluator		(void);
192 
193 	virtual void		evaluate				(ShaderEvalContext& ctx);
194 
195 private:
196 						ShaderEvaluator			(const ShaderEvaluator&);	// not allowed!
197 	ShaderEvaluator&	operator=				(const ShaderEvaluator&);	// not allowed!
198 
199 	ShaderEvalFunc		m_evalFunc;
200 };
201 
202 // ShaderRenderCase.
203 
204 class ShaderRenderCase : public tcu::TestCase
205 {
206 public:
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 
216 protected:
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:
CompileFailed(const char * file,int line)226 		inline CompileFailed (const char* file, int line) : tcu::TestError("Failed to compile shader program", DE_NULL, file, line) {}
227 	};
228 
229 private:
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 
240 protected:
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 
260 const char*		getIntUniformName			(int number);
261 const char*		getFloatUniformName			(int number);
262 const char*		getFloatFractionUniformName	(int number);
263 
264 void			setupDefaultUniforms		(const glu::RenderContext& context, deUint32 programID);
265 
266 } // gls
267 } // deqp
268 
269 #endif // _GLSSHADERRENDERCASE_HPP
270