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