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 } // namespace 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)
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
102 TYPE_LAST
103 };
104
105 TextureBinding(const glu::Texture2D *tex2D, const tcu::Sampler &sampler);
106 TextureBinding(const glu::TextureCube *texCube, const tcu::Sampler &sampler);
107 TextureBinding(const glu::Texture2DArray *tex2DArray, const tcu::Sampler &sampler);
108 TextureBinding(const glu::Texture3D *tex3D, const tcu::Sampler &sampler);
109 TextureBinding(void);
110
111 void setSampler(const tcu::Sampler &sampler);
112 void setTexture(const glu::Texture2D *tex2D);
113 void setTexture(const glu::TextureCube *texCube);
114 void setTexture(const glu::Texture2DArray *tex2DArray);
115 void setTexture(const glu::Texture3D *tex3D);
116
getType(void) const117 Type getType(void) const
118 {
119 return m_type;
120 }
getSampler(void) const121 const tcu::Sampler &getSampler(void) const
122 {
123 return m_sampler;
124 }
get2D(void) const125 const glu::Texture2D *get2D(void) const
126 {
127 DE_ASSERT(getType() == TYPE_2D);
128 return m_binding.tex2D;
129 }
getCube(void) const130 const glu::TextureCube *getCube(void) const
131 {
132 DE_ASSERT(getType() == TYPE_CUBE_MAP);
133 return m_binding.texCube;
134 }
get2DArray(void) const135 const glu::Texture2DArray *get2DArray(void) const
136 {
137 DE_ASSERT(getType() == TYPE_2D_ARRAY);
138 return m_binding.tex2DArray;
139 }
get3D(void) const140 const glu::Texture3D *get3D(void) const
141 {
142 DE_ASSERT(getType() == TYPE_3D);
143 return m_binding.tex3D;
144 }
145
146 private:
147 Type m_type;
148 tcu::Sampler m_sampler;
149 union
150 {
151 const glu::Texture2D *tex2D;
152 const glu::TextureCube *texCube;
153 const glu::Texture2DArray *tex2DArray;
154 const glu::Texture3D *tex3D;
155 } m_binding;
156 };
157
158 // ShaderEvalContext.
159
160 class ShaderEvalContext
161 {
162 public:
163 // Limits.
164 enum
165 {
166 MAX_USER_ATTRIBS = 4,
167 MAX_TEXTURES = 4,
168 };
169
170 struct ShaderSampler
171 {
172 tcu::Sampler sampler;
173 const tcu::Texture2D *tex2D;
174 const tcu::TextureCube *texCube;
175 const tcu::Texture2DArray *tex2DArray;
176 const tcu::Texture3D *tex3D;
177
ShaderSamplerdeqp::gls::ShaderEvalContext::ShaderSampler178 inline ShaderSampler(void) : tex2D(DE_NULL), texCube(DE_NULL), tex2DArray(DE_NULL), tex3D(DE_NULL)
179 {
180 }
181 };
182
183 ShaderEvalContext(const QuadGrid &quadGrid);
184 ~ShaderEvalContext(void);
185
186 void reset(float sx, float sy);
187
188 // Inputs.
189 tcu::Vec4 coords;
190 tcu::Vec4 unitCoords;
191 tcu::Vec4 constCoords;
192
193 tcu::Vec4 in[MAX_USER_ATTRIBS];
194 ShaderSampler textures[MAX_TEXTURES];
195
196 // Output.
197 tcu::Vec4 color;
198 bool isDiscarded;
199
200 // Functions.
discard(void)201 inline void discard(void)
202 {
203 isDiscarded = true;
204 }
205 tcu::Vec4 texture2D(int unitNdx, const tcu::Vec2 &coords);
206
207 private:
208 const QuadGrid &quadGrid;
209 };
210
211 // ShaderEvalFunc.
212
213 typedef void (*ShaderEvalFunc)(ShaderEvalContext &c);
214
evalCoordsPassthroughX(ShaderEvalContext & c)215 inline void evalCoordsPassthroughX(ShaderEvalContext &c)
216 {
217 c.color.x() = c.coords.x();
218 }
evalCoordsPassthroughXY(ShaderEvalContext & c)219 inline void evalCoordsPassthroughXY(ShaderEvalContext &c)
220 {
221 c.color.xy() = c.coords.swizzle(0, 1);
222 }
evalCoordsPassthroughXYZ(ShaderEvalContext & c)223 inline void evalCoordsPassthroughXYZ(ShaderEvalContext &c)
224 {
225 c.color.xyz() = c.coords.swizzle(0, 1, 2);
226 }
evalCoordsPassthrough(ShaderEvalContext & c)227 inline void evalCoordsPassthrough(ShaderEvalContext &c)
228 {
229 c.color = c.coords;
230 }
evalCoordsSwizzleWZYX(ShaderEvalContext & c)231 inline void evalCoordsSwizzleWZYX(ShaderEvalContext &c)
232 {
233 c.color = c.coords.swizzle(3, 2, 1, 0);
234 }
235
236 // ShaderEvaluator
237 // Either inherit a class with overridden evaluate() or just pass in an evalFunc.
238
239 class ShaderEvaluator
240 {
241 public:
242 ShaderEvaluator(void);
243 ShaderEvaluator(ShaderEvalFunc evalFunc);
244 virtual ~ShaderEvaluator(void);
245
246 virtual void evaluate(ShaderEvalContext &ctx);
247
248 private:
249 ShaderEvaluator(const ShaderEvaluator &); // not allowed!
250 ShaderEvaluator &operator=(const ShaderEvaluator &); // not allowed!
251
252 ShaderEvalFunc m_evalFunc;
253 };
254
255 // ShaderRenderCase.
256
257 class ShaderRenderCase : public tcu::TestCase
258 {
259 public:
260 ShaderRenderCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx, const glu::ContextInfo &ctxInfo,
261 const char *name, const char *description, bool isVertexCase, ShaderEvalFunc evalFunc);
262 ShaderRenderCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx, const glu::ContextInfo &ctxInfo,
263 const char *name, const char *description, bool isVertexCase, ShaderEvaluator &evaluator);
264 virtual ~ShaderRenderCase(void);
265
266 void init(void);
267 void deinit(void);
268
269 IterateResult iterate(void);
270
271 protected:
272 virtual void setupShaderData(void);
273 virtual void setup(int programID);
274 virtual void setupUniforms(int programID, const tcu::Vec4 &constCoords);
275
276 tcu::IVec2 getViewportSize(void) const;
277
278 class CompileFailed : public tcu::TestError
279 {
280 public:
CompileFailed(const char * file,int line)281 inline CompileFailed(const char *file, int line)
282 : tcu::TestError("Failed to compile shader program", DE_NULL, file, line)
283 {
284 }
285 };
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 int m_gridSize;
314 };
315
316 // Helpers.
317 // \todo [2012-04-10 pyry] Move these to separate utility?
318
319 const char *getIntUniformName(int number);
320 const char *getFloatUniformName(int number);
321 const char *getFloatFractionUniformName(int number);
322
323 void setupDefaultUniforms(const glu::RenderContext &context, uint32_t programID);
324
325 } // namespace gls
326 } // namespace deqp
327
328 #endif // _GLSSHADERRENDERCASE_HPP
329