• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef _GLCSHADERRENDERCASE_HPP
2 #define _GLCSHADERRENDERCASE_HPP
3 /*-------------------------------------------------------------------------
4  * OpenGL Conformance Test Suite
5  * -----------------------------
6  *
7  * Copyright (c) 2016 Google Inc.
8  * Copyright (c) 2016 The Khronos Group Inc.
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  */ /*!
23  * \file
24  * \brief Shader execute test.
25  */ /*-------------------------------------------------------------------*/
26 
27 #include "glcTestCase.hpp"
28 #include "gluContextInfo.hpp"
29 #include "gluRenderContext.hpp"
30 #include "gluShaderProgram.hpp"
31 #include "tcuDefs.hpp"
32 #include "tcuMatrix.hpp"
33 #include "tcuSurface.hpp"
34 #include "tcuTexture.hpp"
35 #include "tcuVector.hpp"
36 
37 #include <sstream>
38 #include <string>
39 
40 namespace glu
41 {
42 class RenderContext;
43 class Texture2D;
44 class TextureCube;
45 class Texture2DArray;
46 class Texture3D;
47 class TextureCubeArray;
48 } // glu
49 
50 namespace deqp
51 {
52 
53 // LineStream
54 
55 class LineStream
56 {
57 public:
LineStream(int indent=0)58 	LineStream(int indent = 0)
59 	{
60 		m_indent = indent;
61 	}
~LineStream(void)62 	~LineStream(void)
63 	{
64 	}
65 
str(void) const66 	const char* str(void) const
67 	{
68 		m_string = m_stream.str();
69 		return m_string.c_str();
70 	}
operator <<(const char * line)71 	LineStream& operator<<(const char* line)
72 	{
73 		for (int i = 0; i < m_indent; i++)
74 		{
75 			m_stream << "\t";
76 		}
77 		m_stream << line << "\n";
78 		return *this;
79 	}
80 
81 private:
82 	int					m_indent;
83 	std::ostringstream  m_stream;
84 	mutable std::string m_string;
85 };
86 
87 class QuadGrid;
88 
89 // TextureBinding
90 
91 class TextureBinding
92 {
93 public:
94 	enum Type
95 	{
96 		TYPE_NONE = 0,
97 		TYPE_2D,
98 		TYPE_CUBE_MAP,
99 		TYPE_2D_ARRAY,
100 		TYPE_3D,
101 		TYPE_CUBE_MAP_ARRAY,
102 
103 		TYPE_LAST
104 	};
105 
106 	TextureBinding(const glu::Texture2D* tex2D, const tcu::Sampler& sampler);
107 	TextureBinding(const glu::TextureCube* texCube, const tcu::Sampler& sampler);
108 	TextureBinding(const glu::Texture2DArray* tex2DArray, const tcu::Sampler& sampler);
109 	TextureBinding(const glu::Texture3D* tex3D, const tcu::Sampler& sampler);
110 	TextureBinding(const glu::TextureCubeArray* texCubeArray, const tcu::Sampler& sampler);
111 	TextureBinding(void);
112 
113 	void setSampler(const tcu::Sampler& sampler);
114 	void setTexture(const glu::Texture2D* tex2D);
115 	void setTexture(const glu::TextureCube* texCube);
116 	void setTexture(const glu::Texture2DArray* tex2DArray);
117 	void setTexture(const glu::Texture3D* tex3D);
118 	void setTexture(const glu::TextureCubeArray* texCubeArray);
119 
getType(void) const120 	Type getType(void) const
121 	{
122 		return m_type;
123 	}
getSampler(void) const124 	const tcu::Sampler& getSampler(void) const
125 	{
126 		return m_sampler;
127 	}
get2D(void) const128 	const glu::Texture2D* get2D(void) const
129 	{
130 		DE_ASSERT(getType() == TYPE_2D);
131 		return m_binding.tex2D;
132 	}
getCube(void) const133 	const glu::TextureCube* getCube(void) const
134 	{
135 		DE_ASSERT(getType() == TYPE_CUBE_MAP);
136 		return m_binding.texCube;
137 	}
get2DArray(void) const138 	const glu::Texture2DArray* get2DArray(void) const
139 	{
140 		DE_ASSERT(getType() == TYPE_2D_ARRAY);
141 		return m_binding.tex2DArray;
142 	}
get3D(void) const143 	const glu::Texture3D* get3D(void) const
144 	{
145 		DE_ASSERT(getType() == TYPE_3D);
146 		return m_binding.tex3D;
147 	}
getCubeArray(void) const148 	const glu::TextureCubeArray* getCubeArray(void) const
149 	{
150 		DE_ASSERT(getType() == TYPE_CUBE_MAP_ARRAY);
151 		return m_binding.texCubeArray;
152 	}
153 
154 private:
155 	Type		 m_type;
156 	tcu::Sampler m_sampler;
157 	union {
158 		const glu::Texture2D*	  tex2D;
159 		const glu::TextureCube*	texCube;
160 		const glu::Texture2DArray* tex2DArray;
161 		const glu::Texture3D*	  tex3D;
162 		const glu::TextureCubeArray* texCubeArray;
163 	} m_binding;
164 };
165 
166 // ShaderEvalContext.
167 
168 class ShaderEvalContext
169 {
170 public:
171 	// Limits.
172 	enum
173 	{
174 		MAX_USER_ATTRIBS = 4,
175 		MAX_TEXTURES	 = 4,
176 	};
177 
178 	struct ShaderSampler
179 	{
180 		tcu::Sampler			   sampler;
181 		const tcu::Texture2D*	  tex2D;
182 		const tcu::TextureCube*	texCube;
183 		const tcu::Texture2DArray* tex2DArray;
184 		const tcu::Texture3D*	  tex3D;
185 		const tcu::TextureCubeArray* texCubeArray;
186 
ShaderSamplerdeqp::ShaderEvalContext::ShaderSampler187 		inline ShaderSampler(void)
188 			: tex2D(DE_NULL), texCube(DE_NULL), tex2DArray(DE_NULL), tex3D(DE_NULL), texCubeArray(DE_NULL)
189 		{
190 		}
191 	};
192 
193 	ShaderEvalContext(const QuadGrid& quadGrid);
194 	~ShaderEvalContext(void);
195 
196 	void reset(float sx, float sy);
197 
198 	// Inputs.
199 	tcu::Vec4 coords;
200 	tcu::Vec4 unitCoords;
201 	tcu::Vec4 constCoords;
202 
203 	tcu::Vec4	 in[MAX_USER_ATTRIBS];
204 	ShaderSampler textures[MAX_TEXTURES];
205 
206 	// Output.
207 	tcu::Vec4 color;
208 	bool	  isDiscarded;
209 
210 	// Functions.
discard(void)211 	inline void discard(void)
212 	{
213 		isDiscarded = true;
214 	}
215 	tcu::Vec4 texture2D(int unitNdx, const tcu::Vec2& coords);
216 
217 private:
218 	const QuadGrid& quadGrid;
219 };
220 
221 // ShaderEvalFunc.
222 
223 typedef void (*ShaderEvalFunc)(ShaderEvalContext& c);
224 
evalCoordsPassthroughX(ShaderEvalContext & c)225 inline void evalCoordsPassthroughX(ShaderEvalContext& c)
226 {
227 	c.color.x() = c.coords.x();
228 }
evalCoordsPassthroughXY(ShaderEvalContext & c)229 inline void evalCoordsPassthroughXY(ShaderEvalContext& c)
230 {
231 	c.color.xy() = c.coords.swizzle(0, 1);
232 }
evalCoordsPassthroughXYZ(ShaderEvalContext & c)233 inline void evalCoordsPassthroughXYZ(ShaderEvalContext& c)
234 {
235 	c.color.xyz() = c.coords.swizzle(0, 1, 2);
236 }
evalCoordsPassthrough(ShaderEvalContext & c)237 inline void evalCoordsPassthrough(ShaderEvalContext& c)
238 {
239 	c.color = c.coords;
240 }
evalCoordsSwizzleWZYX(ShaderEvalContext & c)241 inline void evalCoordsSwizzleWZYX(ShaderEvalContext& c)
242 {
243 	c.color = c.coords.swizzle(3, 2, 1, 0);
244 }
245 
246 // ShaderEvaluator
247 // Either inherit a class with overridden evaluate() or just pass in an evalFunc.
248 
249 class ShaderEvaluator
250 {
251 public:
252 	ShaderEvaluator(void);
253 	ShaderEvaluator(ShaderEvalFunc evalFunc);
254 	virtual ~ShaderEvaluator(void);
255 
256 	virtual void evaluate(ShaderEvalContext& ctx);
257 
258 private:
259 	ShaderEvaluator(const ShaderEvaluator&);			// not allowed!
260 	ShaderEvaluator& operator=(const ShaderEvaluator&); // not allowed!
261 
262 	ShaderEvalFunc m_evalFunc;
263 };
264 
265 // ShaderRenderCase.
266 
267 class ShaderRenderCase : public tcu::TestCase
268 {
269 public:
270 	ShaderRenderCase(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo,
271 					 const char* name, const char* description, bool isVertexCase, ShaderEvalFunc evalFunc);
272 	ShaderRenderCase(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo,
273 					 const char* name, const char* description, bool isVertexCase, ShaderEvaluator& evaluator);
274 	virtual ~ShaderRenderCase(void);
275 
276 	void init(void);
277 	void deinit(void);
278 
279 	IterateResult iterate(void);
280 
281 protected:
282 	virtual void setup(deUint32 programID);
283 	virtual void setupUniforms(deUint32 programID, const tcu::Vec4& constCoords);
284 
285 	tcu::IVec2 getViewportSize(void) const;
286 
287 private:
288 	ShaderRenderCase(const ShaderRenderCase&);			  // not allowed!
289 	ShaderRenderCase& operator=(const ShaderRenderCase&); // not allowed!
290 
291 	void setupDefaultInputs(int programID);
292 
293 	void render(tcu::Surface& result, int programID, const QuadGrid& quadGrid);
294 	void computeVertexReference(tcu::Surface& result, const QuadGrid& quadGrid);
295 	void computeFragmentReference(tcu::Surface& result, const QuadGrid& quadGrid);
296 	bool compareImages(const tcu::Surface& resImage, const tcu::Surface& refImage, float errorThreshold);
297 
298 protected:
299 	glu::RenderContext&		m_renderCtx;
300 	const glu::ContextInfo& m_ctxInfo;
301 
302 	bool			 m_isVertexCase;
303 	ShaderEvaluator  m_defaultEvaluator;
304 	ShaderEvaluator& m_evaluator;
305 	std::string		 m_vertShaderSource;
306 	std::string		 m_fragShaderSource;
307 	tcu::Vec4		 m_clearColor;
308 
309 	std::vector<tcu::Mat4>		m_userAttribTransforms;
310 	std::vector<TextureBinding> m_textures;
311 
312 	glu::ShaderProgram* m_program;
313 };
314 
315 // Helpers.
316 // \todo [2012-04-10 pyry] Move these to separate utility?
317 
318 const char* getIntUniformName(int number);
319 const char* getFloatUniformName(int number);
320 const char* getFloatFractionUniformName(int number);
321 
322 void setupDefaultUniforms(const glu::RenderContext& context, deUint32 programID);
323 
324 } // deqp
325 
326 #endif // _GLCSHADERRENDERCASE_HPP
327