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 } // namespace 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 {
159 const glu::Texture2D *tex2D;
160 const glu::TextureCube *texCube;
161 const glu::Texture2DArray *tex2DArray;
162 const glu::Texture3D *tex3D;
163 const glu::TextureCubeArray *texCubeArray;
164 } m_binding;
165 };
166
167 // ShaderEvalContext.
168
169 class ShaderEvalContext
170 {
171 public:
172 // Limits.
173 enum
174 {
175 MAX_USER_ATTRIBS = 4,
176 MAX_TEXTURES = 4,
177 };
178
179 struct ShaderSampler
180 {
181 tcu::Sampler sampler;
182 const tcu::Texture2D *tex2D;
183 const tcu::TextureCube *texCube;
184 const tcu::Texture2DArray *tex2DArray;
185 const tcu::Texture3D *tex3D;
186 const tcu::TextureCubeArray *texCubeArray;
187
ShaderSamplerdeqp::ShaderEvalContext::ShaderSampler188 inline ShaderSampler(void)
189 : tex2D(DE_NULL)
190 , texCube(DE_NULL)
191 , tex2DArray(DE_NULL)
192 , tex3D(DE_NULL)
193 , texCubeArray(DE_NULL)
194 {
195 }
196 };
197
198 ShaderEvalContext(const QuadGrid &quadGrid);
199 ~ShaderEvalContext(void);
200
201 void reset(float sx, float sy);
202
203 // Inputs.
204 tcu::Vec4 coords;
205 tcu::Vec4 unitCoords;
206 tcu::Vec4 constCoords;
207
208 tcu::Vec4 in[MAX_USER_ATTRIBS];
209 ShaderSampler textures[MAX_TEXTURES];
210
211 // Output.
212 tcu::Vec4 color;
213 bool isDiscarded;
214
215 // Functions.
discard(void)216 inline void discard(void)
217 {
218 isDiscarded = true;
219 }
220 tcu::Vec4 texture2D(int unitNdx, const tcu::Vec2 &coords);
221
222 private:
223 const QuadGrid &quadGrid;
224 };
225
226 // ShaderEvalFunc.
227
228 typedef void (*ShaderEvalFunc)(ShaderEvalContext &c);
229
evalCoordsPassthroughX(ShaderEvalContext & c)230 inline void evalCoordsPassthroughX(ShaderEvalContext &c)
231 {
232 c.color.x() = c.coords.x();
233 }
evalCoordsPassthroughXY(ShaderEvalContext & c)234 inline void evalCoordsPassthroughXY(ShaderEvalContext &c)
235 {
236 c.color.xy() = c.coords.swizzle(0, 1);
237 }
evalCoordsPassthroughXYZ(ShaderEvalContext & c)238 inline void evalCoordsPassthroughXYZ(ShaderEvalContext &c)
239 {
240 c.color.xyz() = c.coords.swizzle(0, 1, 2);
241 }
evalCoordsPassthrough(ShaderEvalContext & c)242 inline void evalCoordsPassthrough(ShaderEvalContext &c)
243 {
244 c.color = c.coords;
245 }
evalCoordsSwizzleWZYX(ShaderEvalContext & c)246 inline void evalCoordsSwizzleWZYX(ShaderEvalContext &c)
247 {
248 c.color = c.coords.swizzle(3, 2, 1, 0);
249 }
250
251 // ShaderEvaluator
252 // Either inherit a class with overridden evaluate() or just pass in an evalFunc.
253
254 class ShaderEvaluator
255 {
256 public:
257 ShaderEvaluator(void);
258 ShaderEvaluator(ShaderEvalFunc evalFunc);
259 virtual ~ShaderEvaluator(void);
260
261 virtual void evaluate(ShaderEvalContext &ctx);
262
263 private:
264 ShaderEvaluator(const ShaderEvaluator &); // not allowed!
265 ShaderEvaluator &operator=(const ShaderEvaluator &); // not allowed!
266
267 ShaderEvalFunc m_evalFunc;
268 };
269
270 // ShaderRenderCase.
271
272 class ShaderRenderCase : public tcu::TestCase
273 {
274 public:
275 ShaderRenderCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx, const glu::ContextInfo &ctxInfo,
276 const char *name, const char *description, bool isVertexCase, ShaderEvalFunc evalFunc);
277 ShaderRenderCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx, const glu::ContextInfo &ctxInfo,
278 const char *name, const char *description, bool isVertexCase, ShaderEvaluator &evaluator);
279 virtual ~ShaderRenderCase(void);
280
281 void init(void);
282 void deinit(void);
283
284 IterateResult iterate(void);
285
286 protected:
287 virtual void setup(uint32_t programID);
288 virtual void setupUniforms(uint32_t programID, const tcu::Vec4 &constCoords);
289
290 tcu::IVec2 getViewportSize(void) const;
291
292 private:
293 ShaderRenderCase(const ShaderRenderCase &); // not allowed!
294 ShaderRenderCase &operator=(const ShaderRenderCase &); // not allowed!
295
296 void setupDefaultInputs(int programID);
297
298 void render(tcu::Surface &result, int programID, const QuadGrid &quadGrid);
299 void computeVertexReference(tcu::Surface &result, const QuadGrid &quadGrid);
300 void computeFragmentReference(tcu::Surface &result, const QuadGrid &quadGrid);
301 bool compareImages(const tcu::Surface &resImage, const tcu::Surface &refImage, float errorThreshold);
302
303 protected:
304 glu::RenderContext &m_renderCtx;
305 const glu::ContextInfo &m_ctxInfo;
306
307 bool m_isVertexCase;
308 ShaderEvaluator m_defaultEvaluator;
309 ShaderEvaluator &m_evaluator;
310 std::string m_vertShaderSource;
311 std::string m_fragShaderSource;
312 tcu::Vec4 m_clearColor;
313
314 std::vector<tcu::Mat4> m_userAttribTransforms;
315 std::vector<TextureBinding> m_textures;
316
317 glu::ShaderProgram *m_program;
318 };
319
320 // Helpers.
321 // \todo [2012-04-10 pyry] Move these to separate utility?
322
323 const char *getIntUniformName(int number);
324 const char *getFloatUniformName(int number);
325 const char *getFloatFractionUniformName(int number);
326
327 void setupDefaultUniforms(const glu::RenderContext &context, uint32_t programID);
328
329 } // namespace deqp
330
331 #endif // _GLCSHADERRENDERCASE_HPP
332