1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Texture access function tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es2fShaderTextureFunctionTests.hpp"
25 #include "glsShaderRenderCase.hpp"
26 #include "glsShaderLibrary.hpp"
27 #include "glsTextureTestUtil.hpp"
28 #include "gluTexture.hpp"
29 #include "gluTextureUtil.hpp"
30 #include "tcuTextureUtil.hpp"
31 #include "tcuMatrix.hpp"
32 #include "tcuMatrixUtil.hpp"
33
34 #include <sstream>
35
36 #include "glwEnums.hpp"
37 #include "glwFunctions.hpp"
38
39 namespace deqp
40 {
41 namespace gles2
42 {
43 namespace Functional
44 {
45
46 namespace
47 {
48
49 enum Function
50 {
51 FUNCTION_TEXTURE = 0, //!< texture(), textureOffset()
52 FUNCTION_TEXTUREPROJ, //!< textureProj(), textureProjOffset()
53 FUNCTION_TEXTUREPROJ3, //!< textureProj(sampler2D, vec3)
54 FUNCTION_TEXTURELOD, // ...
55 FUNCTION_TEXTUREPROJLOD,
56 FUNCTION_TEXTUREPROJLOD3, //!< textureProjLod(sampler2D, vec3)
57
58 FUNCTION_LAST
59 };
60
functionHasProj(Function function)61 inline bool functionHasProj (Function function)
62 {
63 return function == FUNCTION_TEXTUREPROJ ||
64 function == FUNCTION_TEXTUREPROJ3 ||
65 function == FUNCTION_TEXTUREPROJLOD ||
66 function == FUNCTION_TEXTUREPROJLOD3;
67 }
68
functionHasLod(Function function)69 inline bool functionHasLod (Function function)
70 {
71 return function == FUNCTION_TEXTURELOD ||
72 function == FUNCTION_TEXTUREPROJLOD ||
73 function == FUNCTION_TEXTUREPROJLOD3;
74 }
75
76 struct TextureLookupSpec
77 {
78 Function function;
79
80 tcu::Vec4 minCoord;
81 tcu::Vec4 maxCoord;
82
83 // Bias
84 bool useBias;
85
86 // Bias or Lod for *Lod* functions
87 float minLodBias;
88 float maxLodBias;
89
TextureLookupSpecdeqp::gles2::Functional::__anonaaf110620111::TextureLookupSpec90 TextureLookupSpec (void)
91 : function (FUNCTION_LAST)
92 , minCoord (0.0f)
93 , maxCoord (1.0f)
94 , useBias (false)
95 , minLodBias (0.0f)
96 , maxLodBias (0.0f)
97 {
98 }
99
TextureLookupSpecdeqp::gles2::Functional::__anonaaf110620111::TextureLookupSpec100 TextureLookupSpec (Function function_,
101 const tcu::Vec4& minCoord_,
102 const tcu::Vec4& maxCoord_,
103 bool useBias_,
104 float minLodBias_,
105 float maxLodBias_)
106 : function (function_)
107 , minCoord (minCoord_)
108 , maxCoord (maxCoord_)
109 , useBias (useBias_)
110 , minLodBias (minLodBias_)
111 , maxLodBias (maxLodBias_)
112 {
113 }
114 };
115
116 enum TextureType
117 {
118 TEXTURETYPE_2D,
119 TEXTURETYPE_CUBE_MAP,
120
121 TEXTURETYPE_LAST
122 };
123
124 struct TextureSpec
125 {
126 TextureType type; //!< Texture type (2D, cubemap, ...)
127 deUint32 format;
128 deUint32 dataType;
129 int width;
130 int height;
131 int numLevels;
132 tcu::Sampler sampler;
133
TextureSpecdeqp::gles2::Functional::__anonaaf110620111::TextureSpec134 TextureSpec (void)
135 : type (TEXTURETYPE_LAST)
136 , format (GL_NONE)
137 , dataType (GL_NONE)
138 , width (0)
139 , height (0)
140 , numLevels (0)
141 {
142 }
143
TextureSpecdeqp::gles2::Functional::__anonaaf110620111::TextureSpec144 TextureSpec (TextureType type_,
145 deUint32 format_,
146 deUint32 dataType_,
147 int width_,
148 int height_,
149 int numLevels_,
150 const tcu::Sampler& sampler_)
151 : type (type_)
152 , format (format_)
153 , dataType (dataType_)
154 , width (width_)
155 , height (height_)
156 , numLevels (numLevels_)
157 , sampler (sampler_)
158 {
159 }
160 };
161
162 struct TexLookupParams
163 {
164 float lod;
165 tcu::Vec4 scale;
166 tcu::Vec4 bias;
167
TexLookupParamsdeqp::gles2::Functional::__anonaaf110620111::TexLookupParams168 TexLookupParams (void)
169 : lod (0.0f)
170 , scale (1.0f)
171 , bias (0.0f)
172 {
173 }
174 };
175
176 } // anonymous
177
178 using tcu::Vec2;
179 using tcu::Vec3;
180 using tcu::Vec4;
181 using tcu::IVec2;
182 using tcu::IVec3;
183 using tcu::IVec4;
184
185 typedef void (*TexEvalFunc) (gls::ShaderEvalContext& c, const TexLookupParams& lookupParams);
186
texture2D(const gls::ShaderEvalContext & c,float s,float t,float lod)187 inline Vec4 texture2D (const gls::ShaderEvalContext& c, float s, float t, float lod) { return c.textures[0].tex2D->sample(c.textures[0].sampler, s, t, lod); }
textureCube(const gls::ShaderEvalContext & c,float s,float t,float r,float lod)188 inline Vec4 textureCube (const gls::ShaderEvalContext& c, float s, float t, float r, float lod) { return c.textures[0].texCube->sample(c.textures[0].sampler, s, t, r, lod); }
189
190 // Eval functions.
evalTexture2D(gls::ShaderEvalContext & c,const TexLookupParams & p)191 static void evalTexture2D (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x(), c.in[0].y(), p.lod)*p.scale + p.bias; }
evalTextureCube(gls::ShaderEvalContext & c,const TexLookupParams & p)192 static void evalTextureCube (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod)*p.scale + p.bias; }
193
evalTexture2DBias(gls::ShaderEvalContext & c,const TexLookupParams & p)194 static void evalTexture2DBias (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x(), c.in[0].y(), p.lod+c.in[1].x())*p.scale + p.bias; }
evalTextureCubeBias(gls::ShaderEvalContext & c,const TexLookupParams & p)195 static void evalTextureCubeBias (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod+c.in[1].x())*p.scale + p.bias; }
196
evalTexture2DProj3(gls::ShaderEvalContext & c,const TexLookupParams & p)197 static void evalTexture2DProj3 (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), p.lod)*p.scale + p.bias; }
evalTexture2DProj3Bias(gls::ShaderEvalContext & c,const TexLookupParams & p)198 static void evalTexture2DProj3Bias (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), p.lod+c.in[1].x())*p.scale + p.bias; }
evalTexture2DProj(gls::ShaderEvalContext & c,const TexLookupParams & p)199 static void evalTexture2DProj (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod)*p.scale + p.bias; }
evalTexture2DProjBias(gls::ShaderEvalContext & c,const TexLookupParams & p)200 static void evalTexture2DProjBias (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), p.lod+c.in[1].x())*p.scale + p.bias; }
201
evalTexture2DLod(gls::ShaderEvalContext & c,const TexLookupParams & p)202 static void evalTexture2DLod (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x(), c.in[0].y(), c.in[1].x())*p.scale + p.bias; }
evalTextureCubeLod(gls::ShaderEvalContext & c,const TexLookupParams & p)203 static void evalTextureCubeLod (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[1].x())*p.scale + p.bias; }
204
evalTexture2DProjLod3(gls::ShaderEvalContext & c,const TexLookupParams & p)205 static void evalTexture2DProjLod3 (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].z(), c.in[0].y()/c.in[0].z(), c.in[1].x())*p.scale + p.bias; }
evalTexture2DProjLod(gls::ShaderEvalContext & c,const TexLookupParams & p)206 static void evalTexture2DProjLod (gls::ShaderEvalContext& c, const TexLookupParams& p) { c.color = texture2D(c, c.in[0].x()/c.in[0].w(), c.in[0].y()/c.in[0].w(), c.in[1].x())*p.scale + p.bias; }
207
208 class TexLookupEvaluator : public gls::ShaderEvaluator
209 {
210 public:
TexLookupEvaluator(TexEvalFunc evalFunc,const TexLookupParams & lookupParams)211 TexLookupEvaluator (TexEvalFunc evalFunc, const TexLookupParams& lookupParams) : m_evalFunc(evalFunc), m_lookupParams(lookupParams) {}
212
evaluate(gls::ShaderEvalContext & ctx)213 virtual void evaluate (gls::ShaderEvalContext& ctx) { m_evalFunc(ctx, m_lookupParams); }
214
215 private:
216 TexEvalFunc m_evalFunc;
217 const TexLookupParams& m_lookupParams;
218 };
219
220 class ShaderTextureFunctionCase : public gls::ShaderRenderCase
221 {
222 public:
223 ShaderTextureFunctionCase (Context& context, const char* name, const char* desc, const TextureLookupSpec& lookup, const TextureSpec& texture, TexEvalFunc evalFunc, bool isVertexCase);
224 ~ShaderTextureFunctionCase (void);
225
226 void init (void);
227 void deinit (void);
228
229 protected:
230 void setupUniforms (int programID, const tcu::Vec4& constCoords);
231
232 private:
233 void initTexture (void);
234 void initShaderSources (void);
235
236 TextureLookupSpec m_lookupSpec;
237 TextureSpec m_textureSpec;
238
239 TexLookupParams m_lookupParams;
240 TexLookupEvaluator m_evaluator;
241
242 glu::Texture2D* m_texture2D;
243 glu::TextureCube* m_textureCube;
244 };
245
ShaderTextureFunctionCase(Context & context,const char * name,const char * desc,const TextureLookupSpec & lookup,const TextureSpec & texture,TexEvalFunc evalFunc,bool isVertexCase)246 ShaderTextureFunctionCase::ShaderTextureFunctionCase (Context& context, const char* name, const char* desc, const TextureLookupSpec& lookup, const TextureSpec& texture, TexEvalFunc evalFunc, bool isVertexCase)
247 : gls::ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc, isVertexCase, m_evaluator)
248 , m_lookupSpec (lookup)
249 , m_textureSpec (texture)
250 , m_evaluator (evalFunc, m_lookupParams)
251 , m_texture2D (DE_NULL)
252 , m_textureCube (DE_NULL)
253 {
254 }
255
~ShaderTextureFunctionCase(void)256 ShaderTextureFunctionCase::~ShaderTextureFunctionCase (void)
257 {
258 delete m_texture2D;
259 delete m_textureCube;
260 }
261
init(void)262 void ShaderTextureFunctionCase::init (void)
263 {
264 if (m_isVertexCase)
265 {
266 const glw::Functions& gl = m_renderCtx.getFunctions();
267 int numVertexUnits = 0;
268 gl.getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &numVertexUnits);
269 if (numVertexUnits < 1)
270 throw tcu::NotSupportedError("Vertex shader texture access is not supported");
271 }
272
273 {
274 // Base coord scale & bias
275 Vec4 s = m_lookupSpec.maxCoord-m_lookupSpec.minCoord;
276 Vec4 b = m_lookupSpec.minCoord;
277
278 float baseCoordTrans[] =
279 {
280 s.x(), 0.0f, 0.f, b.x(),
281 0.f, s.y(), 0.f, b.y(),
282 s.z()/2.f, -s.z()/2.f, 0.f, s.z()/2.f + b.z(),
283 -s.w()/2.f, s.w()/2.f, 0.f, s.w()/2.f + b.w()
284 };
285
286 m_userAttribTransforms.push_back(tcu::Mat4(baseCoordTrans));
287 }
288
289 if (functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias)
290 {
291 float s = m_lookupSpec.maxLodBias-m_lookupSpec.minLodBias;
292 float b = m_lookupSpec.minLodBias;
293 float lodCoordTrans[] =
294 {
295 s/2.0f, s/2.0f, 0.f, b,
296 0.0f, 0.0f, 0.0f, 0.0f,
297 0.0f, 0.0f, 0.0f, 0.0f,
298 0.0f, 0.0f, 0.0f, 0.0f
299 };
300
301 m_userAttribTransforms.push_back(tcu::Mat4(lodCoordTrans));
302 }
303
304 initShaderSources();
305 initTexture();
306
307 gls::ShaderRenderCase::init();
308 }
309
initTexture(void)310 void ShaderTextureFunctionCase::initTexture (void)
311 {
312 static const IVec4 texCubeSwz[] =
313 {
314 IVec4(0,0,1,1),
315 IVec4(1,1,0,0),
316 IVec4(0,1,0,1),
317 IVec4(1,0,1,0),
318 IVec4(0,1,1,0),
319 IVec4(1,0,0,1)
320 };
321 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(texCubeSwz) == tcu::CUBEFACE_LAST);
322
323 tcu::TextureFormat texFmt = glu::mapGLTransferFormat(m_textureSpec.format, m_textureSpec.dataType);
324 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
325 tcu::IVec2 viewportSize = getViewportSize();
326 bool isProj = functionHasProj(m_lookupSpec.function);
327 float proj = isProj ? 1.0f/m_lookupSpec.minCoord[m_lookupSpec.function == FUNCTION_TEXTUREPROJ3 ? 2 : 3] : 1.0f;
328
329 switch (m_textureSpec.type)
330 {
331 case TEXTURETYPE_2D:
332 {
333 float cStep = 1.0f / (float)de::max(1, m_textureSpec.numLevels-1);
334 Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
335 Vec4 cBias = fmtInfo.valueMin;
336 int baseCellSize = de::min(m_textureSpec.width/4, m_textureSpec.height/4);
337
338 m_texture2D = new glu::Texture2D(m_renderCtx, m_textureSpec.format, m_textureSpec.dataType, m_textureSpec.width, m_textureSpec.height);
339 for (int level = 0; level < m_textureSpec.numLevels; level++)
340 {
341 float fA = float(level)*cStep;
342 float fB = 1.0f-fA;
343 Vec4 colorA = cBias + cScale*Vec4(fA, fB, fA, fB);
344 Vec4 colorB = cBias + cScale*Vec4(fB, fA, fB, fA);
345
346 m_texture2D->getRefTexture().allocLevel(level);
347 tcu::fillWithGrid(m_texture2D->getRefTexture().getLevel(level), de::max(1, baseCellSize>>level), colorA, colorB);
348 }
349 m_texture2D->upload();
350
351 // Compute LOD.
352 float dudx = (m_lookupSpec.maxCoord[0]-m_lookupSpec.minCoord[0])*proj*(float)m_textureSpec.width / (float)viewportSize[0];
353 float dvdy = (m_lookupSpec.maxCoord[1]-m_lookupSpec.minCoord[1])*proj*(float)m_textureSpec.height / (float)viewportSize[1];
354 m_lookupParams.lod = gls::TextureTestUtil::computeLodFromDerivates(gls::TextureTestUtil::LODMODE_EXACT, dudx, 0.0f, 0.0f, dvdy);
355
356 // Append to texture list.
357 m_textures.push_back(gls::TextureBinding(m_texture2D, m_textureSpec.sampler));
358 break;
359 }
360
361 case TEXTURETYPE_CUBE_MAP:
362 {
363 float cStep = 1.0f / (float)de::max(1, m_textureSpec.numLevels-1);
364 Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
365 Vec4 cBias = fmtInfo.valueMin;
366 int baseCellSize = de::min(m_textureSpec.width/4, m_textureSpec.height/4);
367
368 DE_ASSERT(m_textureSpec.width == m_textureSpec.height);
369 m_textureCube = new glu::TextureCube(m_renderCtx, m_textureSpec.format, m_textureSpec.dataType, m_textureSpec.width);
370 for (int level = 0; level < m_textureSpec.numLevels; level++)
371 {
372 float fA = float(level)*cStep;
373 float fB = 1.0f-fA;
374 Vec2 f (fA, fB);
375
376 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
377 {
378 const IVec4& swzA = texCubeSwz[face];
379 IVec4 swzB = 1-swzA;
380 Vec4 colorA = cBias + cScale*f.swizzle(swzA[0], swzA[1], swzA[2], swzA[3]);
381 Vec4 colorB = cBias + cScale*f.swizzle(swzB[0], swzB[1], swzB[2], swzB[3]);
382
383 m_textureCube->getRefTexture().allocLevel((tcu::CubeFace)face, level);
384 tcu::fillWithGrid(m_textureCube->getRefTexture().getLevelFace(level, (tcu::CubeFace)face), de::max(1, baseCellSize>>level), colorA, colorB);
385 }
386 }
387 m_textureCube->upload();
388
389 // Compute LOD \note Assumes that only single side is accessed and R is constant major axis.
390 DE_ASSERT(de::abs(m_lookupSpec.minCoord[2] - m_lookupSpec.maxCoord[2]) < 0.005);
391 DE_ASSERT(de::abs(m_lookupSpec.minCoord[0]) < de::abs(m_lookupSpec.minCoord[2]) && de::abs(m_lookupSpec.maxCoord[0]) < de::abs(m_lookupSpec.minCoord[2]));
392 DE_ASSERT(de::abs(m_lookupSpec.minCoord[1]) < de::abs(m_lookupSpec.minCoord[2]) && de::abs(m_lookupSpec.maxCoord[1]) < de::abs(m_lookupSpec.minCoord[2]));
393
394 tcu::CubeFaceFloatCoords c00 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.minCoord[0]*proj, m_lookupSpec.minCoord[1]*proj, m_lookupSpec.minCoord[2]*proj));
395 tcu::CubeFaceFloatCoords c10 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.maxCoord[0]*proj, m_lookupSpec.minCoord[1]*proj, m_lookupSpec.minCoord[2]*proj));
396 tcu::CubeFaceFloatCoords c01 = tcu::getCubeFaceCoords(Vec3(m_lookupSpec.minCoord[0]*proj, m_lookupSpec.maxCoord[1]*proj, m_lookupSpec.minCoord[2]*proj));
397 float dudx = (c10.s - c00.s)*(float)m_textureSpec.width / (float)viewportSize[0];
398 float dvdy = (c01.t - c00.t)*(float)m_textureSpec.height / (float)viewportSize[1];
399
400 m_lookupParams.lod = gls::TextureTestUtil::computeLodFromDerivates(gls::TextureTestUtil::LODMODE_EXACT, dudx, 0.0f, 0.0f, dvdy);
401
402 m_textures.push_back(gls::TextureBinding(m_textureCube, m_textureSpec.sampler));
403 break;
404 }
405
406 default:
407 DE_ASSERT(DE_FALSE);
408 }
409
410 // Set lookup scale & bias
411 m_lookupParams.scale = fmtInfo.lookupScale;
412 m_lookupParams.bias = fmtInfo.lookupBias;
413 }
414
initShaderSources(void)415 void ShaderTextureFunctionCase::initShaderSources (void)
416 {
417 Function function = m_lookupSpec.function;
418 bool isVtxCase = m_isVertexCase;
419 bool isProj = functionHasProj(function);
420 bool is2DProj4 = m_textureSpec.type == TEXTURETYPE_2D && (function == FUNCTION_TEXTUREPROJ || function == FUNCTION_TEXTUREPROJLOD);
421 bool hasLodBias = functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias;
422 int texCoordComps = m_textureSpec.type == TEXTURETYPE_2D ? 2 : 3;
423 int extraCoordComps = isProj ? (is2DProj4 ? 2 : 1) : 0;
424 glu::DataType coordType = glu::getDataTypeFloatVec(texCoordComps+extraCoordComps);
425 glu::Precision coordPrec = glu::PRECISION_MEDIUMP;
426 const char* coordTypeName = glu::getDataTypeName(coordType);
427 const char* coordPrecName = glu::getPrecisionName(coordPrec);
428 tcu::TextureFormat texFmt = glu::mapGLTransferFormat(m_textureSpec.format, m_textureSpec.dataType);
429 glu::DataType samplerType = glu::TYPE_LAST;
430 const char* baseFuncName = m_textureSpec.type == TEXTURETYPE_2D ? "texture2D" : "textureCube";
431 const char* funcExt = DE_NULL;
432
433 switch (m_textureSpec.type)
434 {
435 case TEXTURETYPE_2D: samplerType = glu::getSampler2DType(texFmt); break;
436 case TEXTURETYPE_CUBE_MAP: samplerType = glu::getSamplerCubeType(texFmt); break;
437 default:
438 DE_ASSERT(DE_FALSE);
439 }
440
441 switch (m_lookupSpec.function)
442 {
443 case FUNCTION_TEXTURE: funcExt = ""; break;
444 case FUNCTION_TEXTUREPROJ: funcExt = "Proj"; break;
445 case FUNCTION_TEXTUREPROJ3: funcExt = "Proj"; break;
446 case FUNCTION_TEXTURELOD: funcExt = "Lod"; break;
447 case FUNCTION_TEXTUREPROJLOD: funcExt = "ProjLod"; break;
448 case FUNCTION_TEXTUREPROJLOD3: funcExt = "ProjLod"; break;
449 default:
450 DE_ASSERT(DE_FALSE);
451 }
452
453 std::ostringstream vert;
454 std::ostringstream frag;
455 std::ostringstream& op = isVtxCase ? vert : frag;
456
457 vert << "attribute highp vec4 a_position;\n"
458 << "attribute " << coordPrecName << " " << coordTypeName << " a_in0;\n";
459
460 if (hasLodBias)
461 vert << "attribute " << coordPrecName << " float a_in1;\n";
462
463 if (isVtxCase)
464 {
465 vert << "varying mediump vec4 v_color;\n";
466 frag << "varying mediump vec4 v_color;\n";
467 }
468 else
469 {
470 vert << "varying " << coordPrecName << " " << coordTypeName << " v_texCoord;\n";
471 frag << "varying " << coordPrecName << " " << coordTypeName << " v_texCoord;\n";
472
473 if (hasLodBias)
474 {
475 vert << "varying " << coordPrecName << " float v_lodBias;\n";
476 frag << "varying " << coordPrecName << " float v_lodBias;\n";
477 }
478 }
479
480 // Uniforms
481 op << "uniform lowp " << glu::getDataTypeName(samplerType) << " u_sampler;\n";
482
483 vert << "\nvoid main()\n{\n"
484 << "\tgl_Position = a_position;\n";
485 frag << "\nvoid main()\n{\n";
486
487 if (isVtxCase)
488 vert << "\tv_color = ";
489 else
490 frag << "\tgl_FragColor = ";
491
492 // Op.
493 {
494 const char* texCoord = isVtxCase ? "a_in0" : "v_texCoord";
495 const char* lodBias = isVtxCase ? "a_in1" : "v_lodBias";
496
497 op << baseFuncName << funcExt;
498 op << "(u_sampler, " << texCoord;
499
500 if (functionHasLod(function) || m_lookupSpec.useBias)
501 op << ", " << lodBias;
502
503 op << ");\n";
504 }
505
506 if (isVtxCase)
507 frag << "\tgl_FragColor = v_color;\n";
508 else
509 {
510 vert << "\tv_texCoord = a_in0;\n";
511
512 if (hasLodBias)
513 vert << "\tv_lodBias = a_in1;\n";
514 }
515
516 vert << "}\n";
517 frag << "}\n";
518
519 m_vertShaderSource = vert.str();
520 m_fragShaderSource = frag.str();
521 }
522
deinit(void)523 void ShaderTextureFunctionCase::deinit (void)
524 {
525 gls::ShaderRenderCase::deinit();
526
527 delete m_texture2D;
528 delete m_textureCube;
529
530 m_texture2D = DE_NULL;
531 m_textureCube = DE_NULL;
532 }
533
setupUniforms(int programID,const tcu::Vec4 &)534 void ShaderTextureFunctionCase::setupUniforms (int programID, const tcu::Vec4&)
535 {
536 const glw::Functions& gl = m_renderCtx.getFunctions();
537 gl.uniform1i(gl.getUniformLocation(programID, "u_sampler"), 0);
538 }
539
ShaderTextureFunctionTests(Context & context)540 ShaderTextureFunctionTests::ShaderTextureFunctionTests (Context& context)
541 : TestCaseGroup(context, "texture_functions", "Texture Access Function Tests")
542 {
543 }
544
~ShaderTextureFunctionTests(void)545 ShaderTextureFunctionTests::~ShaderTextureFunctionTests (void)
546 {
547 }
548
549 struct TexFuncCaseSpec
550 {
551 const char* name;
552 TextureLookupSpec lookupSpec;
553 TextureSpec texSpec;
554 TexEvalFunc evalFunc;
555 };
556
557 #define CASE_SPEC(NAME, FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD, TEXSPEC, EVALFUNC) \
558 { #NAME, TextureLookupSpec(FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD), TEXSPEC, EVALFUNC }
559
createCaseGroup(TestCaseGroup * parent,const char * groupName,const char * groupDesc,const TexFuncCaseSpec * cases,int numCases,bool isVertex)560 static void createCaseGroup (TestCaseGroup* parent, const char* groupName, const char* groupDesc, const TexFuncCaseSpec* cases, int numCases, bool isVertex)
561 {
562 tcu::TestCaseGroup* group = new tcu::TestCaseGroup(parent->getTestContext(), groupName, groupDesc);
563 parent->addChild(group);
564
565 for (int ndx = 0; ndx < numCases; ndx++)
566 group->addChild(new ShaderTextureFunctionCase(parent->getContext(), cases[ndx].name, "", cases[ndx].lookupSpec, cases[ndx].texSpec, cases[ndx].evalFunc, isVertex));
567 }
568
init(void)569 void ShaderTextureFunctionTests::init (void)
570 {
571 // Samplers
572 static const tcu::Sampler samplerLinearNoMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
573 tcu::Sampler::LINEAR, tcu::Sampler::LINEAR);
574 static const tcu::Sampler samplerLinearMipmap (tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
575 tcu::Sampler::LINEAR_MIPMAP_NEAREST, tcu::Sampler::LINEAR);
576
577 // Default textures.
578 // Type Format DataType W H L Sampler
579 static const TextureSpec tex2D (TEXTURETYPE_2D, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 1, samplerLinearNoMipmap);
580 static const TextureSpec tex2DMipmap (TEXTURETYPE_2D, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 9, samplerLinearMipmap);
581
582 static const TextureSpec texCube (TEXTURETYPE_CUBE_MAP, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 1, samplerLinearNoMipmap);
583 static const TextureSpec texCubeMipmap (TEXTURETYPE_CUBE_MAP, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 9, samplerLinearMipmap);
584
585 // Vertex cases
586 static const TexFuncCaseSpec vertexCases[] =
587 {
588 // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Texture EvalFunc
589 CASE_SPEC(texture2d, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), false, 0.0f, 0.0f, tex2D, evalTexture2D),
590 // CASE_SPEC(texture2d_bias, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), true, -2.0f, 2.0f, tex2D, evalTexture2DBias),
591 CASE_SPEC(texture2dproj_vec3, FUNCTION_TEXTUREPROJ3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), false, 0.0f, 0.0f, tex2D, evalTexture2DProj3),
592 CASE_SPEC(texture2dproj_vec4, FUNCTION_TEXTUREPROJ, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), false, 0.0f, 0.0f, tex2D, evalTexture2DProj),
593 CASE_SPEC(texture2dlod, FUNCTION_TEXTURELOD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), false, -1.0f, 9.0f, tex2DMipmap, evalTexture2DLod),
594 // CASE_SPEC(texture2dproj_vec3_bias, FUNCTION_TEXTUREPROJ3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), true, -2.0f, 2.0f, tex2D, evalTexture2DProj3Bias),
595 // CASE_SPEC(texture2dproj_vec4_bias, FUNCTION_TEXTUREPROJ, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), true, -2.0f, 2.0f, tex2D, evalTexture2DProjBias),
596 CASE_SPEC(texture2dprojlod_vec3, FUNCTION_TEXTUREPROJLOD3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), false, -1.0f, 9.0f, tex2D, evalTexture2DProjLod3),
597 CASE_SPEC(texture2dprojlod_vec4, FUNCTION_TEXTUREPROJLOD, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), false, -1.0f, 9.0f, tex2D, evalTexture2DProjLod),
598 CASE_SPEC(texturecube, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4( 1.0f, 1.0f, 1.01f, 0.0f), false, 0.0f, 0.0f, texCube, evalTextureCube),
599 // CASE_SPEC(texturecube_bias, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, -1.01f, 0.0f), Vec4( 1.0f, 1.0f, -1.01f, 0.0f), true, -2.0f, 2.0f, texCube, evalTextureCubeBias),
600 CASE_SPEC(texturecubelod, FUNCTION_TEXTURELOD, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4( 1.0f, 1.0f, 1.01f, 0.0f), false, -1.0f, 9.0f, texCubeMipmap, evalTextureCubeLod),
601 };
602 createCaseGroup(this, "vertex", "Vertex Shader Texture Lookups", &vertexCases[0], DE_LENGTH_OF_ARRAY(vertexCases), true);
603
604 // Fragment cases
605 static const TexFuncCaseSpec fragmentCases[] =
606 {
607 // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Texture EvalFunc
608 CASE_SPEC(texture2d, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), false, 0.0f, 0.0f, tex2DMipmap, evalTexture2D),
609 CASE_SPEC(texture2d_bias, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4( 1.5f, 2.3f, 0.0f, 0.0f), true, -2.0f, 2.0f, tex2DMipmap, evalTexture2DBias),
610 CASE_SPEC(texture2dproj_vec3, FUNCTION_TEXTUREPROJ3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), false, 0.0f, 0.0f, tex2DMipmap, evalTexture2DProj3),
611 CASE_SPEC(texture2dproj_vec4, FUNCTION_TEXTUREPROJ, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), false, 0.0f, 0.0f, tex2DMipmap, evalTexture2DProj),
612 CASE_SPEC(texture2dproj_vec3_bias, FUNCTION_TEXTUREPROJ3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f), Vec4(2.25f, 3.45f, 1.5f, 0.0f), true, -2.0f, 2.0f, tex2DMipmap, evalTexture2DProj3Bias),
613 CASE_SPEC(texture2dproj_vec4_bias, FUNCTION_TEXTUREPROJ, Vec4(-0.3f, -0.6f, 0.0f, 1.5f), Vec4(2.25f, 3.45f, 0.0f, 1.5f), true, -2.0f, 2.0f, tex2DMipmap, evalTexture2DProjBias),
614 CASE_SPEC(texturecube, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4( 1.0f, 1.0f, 1.01f, 0.0f), false, 0.0f, 0.0f, texCubeMipmap, evalTextureCube),
615 CASE_SPEC(texturecube_bias, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, -1.01f, 0.0f), Vec4( 1.0f, 1.0f, -1.01f, 0.0f), true, -2.0f, 2.0f, texCubeMipmap, evalTextureCubeBias)
616 };
617 createCaseGroup(this, "fragment", "Fragment Shader Texture Lookups", &fragmentCases[0], DE_LENGTH_OF_ARRAY(fragmentCases), false);
618
619 // Negative cases.
620 {
621 gls::ShaderLibrary library(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo());
622 std::vector<tcu::TestNode*> negativeCases = library.loadShaderFile("shaders/invalid_texture_functions.test");
623
624 tcu::TestCaseGroup* group = new tcu::TestCaseGroup(m_testCtx, "invalid", "Invalid texture function usage", negativeCases);
625 addChild(group);
626 }
627 }
628
629 } // Functional
630 } // gles3
631 } // deqp
632