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 || function == FUNCTION_TEXTUREPROJ3 ||
64 function == FUNCTION_TEXTUREPROJLOD || function == FUNCTION_TEXTUREPROJLOD3;
65 }
66
functionHasLod(Function function)67 inline bool functionHasLod(Function function)
68 {
69 return function == FUNCTION_TEXTURELOD || function == FUNCTION_TEXTUREPROJLOD ||
70 function == FUNCTION_TEXTUREPROJLOD3;
71 }
72
73 struct TextureLookupSpec
74 {
75 Function function;
76
77 tcu::Vec4 minCoord;
78 tcu::Vec4 maxCoord;
79
80 // Bias
81 bool useBias;
82
83 // Bias or Lod for *Lod* functions
84 float minLodBias;
85 float maxLodBias;
86
TextureLookupSpecdeqp::gles2::Functional::__anone1ab98580111::TextureLookupSpec87 TextureLookupSpec(void)
88 : function(FUNCTION_LAST)
89 , minCoord(0.0f)
90 , maxCoord(1.0f)
91 , useBias(false)
92 , minLodBias(0.0f)
93 , maxLodBias(0.0f)
94 {
95 }
96
TextureLookupSpecdeqp::gles2::Functional::__anone1ab98580111::TextureLookupSpec97 TextureLookupSpec(Function function_, const tcu::Vec4 &minCoord_, const tcu::Vec4 &maxCoord_, bool useBias_,
98 float minLodBias_, float maxLodBias_)
99 : function(function_)
100 , minCoord(minCoord_)
101 , maxCoord(maxCoord_)
102 , useBias(useBias_)
103 , minLodBias(minLodBias_)
104 , maxLodBias(maxLodBias_)
105 {
106 }
107 };
108
109 enum TextureType
110 {
111 TEXTURETYPE_2D,
112 TEXTURETYPE_CUBE_MAP,
113
114 TEXTURETYPE_LAST
115 };
116
117 struct TextureSpec
118 {
119 TextureType type; //!< Texture type (2D, cubemap, ...)
120 uint32_t format;
121 uint32_t dataType;
122 int width;
123 int height;
124 int numLevels;
125 tcu::Sampler sampler;
126
TextureSpecdeqp::gles2::Functional::__anone1ab98580111::TextureSpec127 TextureSpec(void) : type(TEXTURETYPE_LAST), format(GL_NONE), dataType(GL_NONE), width(0), height(0), numLevels(0)
128 {
129 }
130
TextureSpecdeqp::gles2::Functional::__anone1ab98580111::TextureSpec131 TextureSpec(TextureType type_, uint32_t format_, uint32_t dataType_, int width_, int height_, int numLevels_,
132 const tcu::Sampler &sampler_)
133 : type(type_)
134 , format(format_)
135 , dataType(dataType_)
136 , width(width_)
137 , height(height_)
138 , numLevels(numLevels_)
139 , sampler(sampler_)
140 {
141 }
142 };
143
144 struct TexLookupParams
145 {
146 float lod;
147 tcu::Vec4 scale;
148 tcu::Vec4 bias;
149
TexLookupParamsdeqp::gles2::Functional::__anone1ab98580111::TexLookupParams150 TexLookupParams(void) : lod(0.0f), scale(1.0f), bias(0.0f)
151 {
152 }
153 };
154
155 } // namespace
156
157 using tcu::IVec2;
158 using tcu::IVec3;
159 using tcu::IVec4;
160 using tcu::Vec2;
161 using tcu::Vec3;
162 using tcu::Vec4;
163
164 typedef void (*TexEvalFunc)(gls::ShaderEvalContext &c, const TexLookupParams &lookupParams);
165
texture2D(const gls::ShaderEvalContext & c,float s,float t,float lod)166 inline Vec4 texture2D(const gls::ShaderEvalContext &c, float s, float t, float lod)
167 {
168 return c.textures[0].tex2D->sample(c.textures[0].sampler, s, t, lod);
169 }
textureCube(const gls::ShaderEvalContext & c,float s,float t,float r,float lod)170 inline Vec4 textureCube(const gls::ShaderEvalContext &c, float s, float t, float r, float lod)
171 {
172 return c.textures[0].texCube->sample(c.textures[0].sampler, s, t, r, lod);
173 }
174
175 // Eval functions.
evalTexture2D(gls::ShaderEvalContext & c,const TexLookupParams & p)176 static void evalTexture2D(gls::ShaderEvalContext &c, const TexLookupParams &p)
177 {
178 c.color = texture2D(c, c.in[0].x(), c.in[0].y(), p.lod) * p.scale + p.bias;
179 }
evalTextureCube(gls::ShaderEvalContext & c,const TexLookupParams & p)180 static void evalTextureCube(gls::ShaderEvalContext &c, const TexLookupParams &p)
181 {
182 c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), p.lod) * p.scale + p.bias;
183 }
184
evalTexture2DBias(gls::ShaderEvalContext & c,const TexLookupParams & p)185 static void evalTexture2DBias(gls::ShaderEvalContext &c, const TexLookupParams &p)
186 {
187 c.color = texture2D(c, c.in[0].x(), c.in[0].y(), p.lod + c.in[1].x()) * p.scale + p.bias;
188 }
evalTextureCubeBias(gls::ShaderEvalContext & c,const TexLookupParams & p)189 static void evalTextureCubeBias(gls::ShaderEvalContext &c, const TexLookupParams &p)
190 {
191 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;
192 }
193
evalTexture2DProj3(gls::ShaderEvalContext & c,const TexLookupParams & p)194 static void evalTexture2DProj3(gls::ShaderEvalContext &c, const TexLookupParams &p)
195 {
196 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;
197 }
evalTexture2DProj3Bias(gls::ShaderEvalContext & c,const TexLookupParams & p)198 static void evalTexture2DProj3Bias(gls::ShaderEvalContext &c, const TexLookupParams &p)
199 {
200 c.color =
201 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;
202 }
evalTexture2DProj(gls::ShaderEvalContext & c,const TexLookupParams & p)203 static void evalTexture2DProj(gls::ShaderEvalContext &c, const TexLookupParams &p)
204 {
205 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;
206 }
evalTexture2DProjBias(gls::ShaderEvalContext & c,const TexLookupParams & p)207 static void evalTexture2DProjBias(gls::ShaderEvalContext &c, const TexLookupParams &p)
208 {
209 c.color =
210 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;
211 }
212
evalTexture2DLod(gls::ShaderEvalContext & c,const TexLookupParams & p)213 static void evalTexture2DLod(gls::ShaderEvalContext &c, const TexLookupParams &p)
214 {
215 c.color = texture2D(c, c.in[0].x(), c.in[0].y(), c.in[1].x()) * p.scale + p.bias;
216 }
evalTextureCubeLod(gls::ShaderEvalContext & c,const TexLookupParams & p)217 static void evalTextureCubeLod(gls::ShaderEvalContext &c, const TexLookupParams &p)
218 {
219 c.color = textureCube(c, c.in[0].x(), c.in[0].y(), c.in[0].z(), c.in[1].x()) * p.scale + p.bias;
220 }
221
evalTexture2DProjLod3(gls::ShaderEvalContext & c,const TexLookupParams & p)222 static void evalTexture2DProjLod3(gls::ShaderEvalContext &c, const TexLookupParams &p)
223 {
224 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;
225 }
evalTexture2DProjLod(gls::ShaderEvalContext & c,const TexLookupParams & p)226 static void evalTexture2DProjLod(gls::ShaderEvalContext &c, const TexLookupParams &p)
227 {
228 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;
229 }
230
231 class TexLookupEvaluator : public gls::ShaderEvaluator
232 {
233 public:
TexLookupEvaluator(TexEvalFunc evalFunc,const TexLookupParams & lookupParams)234 TexLookupEvaluator(TexEvalFunc evalFunc, const TexLookupParams &lookupParams)
235 : m_evalFunc(evalFunc)
236 , m_lookupParams(lookupParams)
237 {
238 }
239
evaluate(gls::ShaderEvalContext & ctx)240 virtual void evaluate(gls::ShaderEvalContext &ctx)
241 {
242 m_evalFunc(ctx, m_lookupParams);
243 }
244
245 private:
246 TexEvalFunc m_evalFunc;
247 const TexLookupParams &m_lookupParams;
248 };
249
250 class ShaderTextureFunctionCase : public gls::ShaderRenderCase
251 {
252 public:
253 ShaderTextureFunctionCase(Context &context, const char *name, const char *desc, const TextureLookupSpec &lookup,
254 const TextureSpec &texture, TexEvalFunc evalFunc, bool isVertexCase);
255 ~ShaderTextureFunctionCase(void);
256
257 void init(void);
258 void deinit(void);
259
260 protected:
261 void setupUniforms(int programID, const tcu::Vec4 &constCoords);
262
263 private:
264 void initTexture(void);
265 void initShaderSources(void);
266
267 TextureLookupSpec m_lookupSpec;
268 TextureSpec m_textureSpec;
269
270 TexLookupParams m_lookupParams;
271 TexLookupEvaluator m_evaluator;
272
273 glu::Texture2D *m_texture2D;
274 glu::TextureCube *m_textureCube;
275 };
276
ShaderTextureFunctionCase(Context & context,const char * name,const char * desc,const TextureLookupSpec & lookup,const TextureSpec & texture,TexEvalFunc evalFunc,bool isVertexCase)277 ShaderTextureFunctionCase::ShaderTextureFunctionCase(Context &context, const char *name, const char *desc,
278 const TextureLookupSpec &lookup, const TextureSpec &texture,
279 TexEvalFunc evalFunc, bool isVertexCase)
280 : gls::ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc,
281 isVertexCase, m_evaluator)
282 , m_lookupSpec(lookup)
283 , m_textureSpec(texture)
284 , m_evaluator(evalFunc, m_lookupParams)
285 , m_texture2D(DE_NULL)
286 , m_textureCube(DE_NULL)
287 {
288 }
289
~ShaderTextureFunctionCase(void)290 ShaderTextureFunctionCase::~ShaderTextureFunctionCase(void)
291 {
292 delete m_texture2D;
293 delete m_textureCube;
294 }
295
init(void)296 void ShaderTextureFunctionCase::init(void)
297 {
298 if (m_isVertexCase)
299 {
300 const glw::Functions &gl = m_renderCtx.getFunctions();
301 int numVertexUnits = 0;
302 gl.getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &numVertexUnits);
303 if (numVertexUnits < 1)
304 throw tcu::NotSupportedError("Vertex shader texture access is not supported");
305 }
306
307 {
308 // Base coord scale & bias
309 Vec4 s = m_lookupSpec.maxCoord - m_lookupSpec.minCoord;
310 Vec4 b = m_lookupSpec.minCoord;
311
312 float baseCoordTrans[] = {s.x(), 0.0f, 0.f, b.x(),
313 0.f, s.y(), 0.f, b.y(),
314 s.z() / 2.f, -s.z() / 2.f, 0.f, s.z() / 2.f + b.z(),
315 -s.w() / 2.f, s.w() / 2.f, 0.f, s.w() / 2.f + b.w()};
316
317 m_userAttribTransforms.push_back(tcu::Mat4(baseCoordTrans));
318 }
319
320 if (functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias)
321 {
322 float s = m_lookupSpec.maxLodBias - m_lookupSpec.minLodBias;
323 float b = m_lookupSpec.minLodBias;
324 float lodCoordTrans[] = {s / 2.0f, s / 2.0f, 0.f, b, 0.0f, 0.0f, 0.0f, 0.0f,
325 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
326
327 m_userAttribTransforms.push_back(tcu::Mat4(lodCoordTrans));
328 }
329
330 initShaderSources();
331 initTexture();
332
333 gls::ShaderRenderCase::init();
334 }
335
initTexture(void)336 void ShaderTextureFunctionCase::initTexture(void)
337 {
338 static const IVec4 texCubeSwz[] = {IVec4(0, 0, 1, 1), IVec4(1, 1, 0, 0), IVec4(0, 1, 0, 1),
339 IVec4(1, 0, 1, 0), IVec4(0, 1, 1, 0), IVec4(1, 0, 0, 1)};
340 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(texCubeSwz) == tcu::CUBEFACE_LAST);
341
342 tcu::TextureFormat texFmt = glu::mapGLTransferFormat(m_textureSpec.format, m_textureSpec.dataType);
343 tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
344 tcu::IVec2 viewportSize = getViewportSize();
345 bool useProj = functionHasProj(m_lookupSpec.function) && !functionHasLod(m_lookupSpec.function);
346 float proj = useProj ? 1.0f / m_lookupSpec.minCoord[m_lookupSpec.function == FUNCTION_TEXTUREPROJ3 ? 2 : 3] : 1.0f;
347
348 switch (m_textureSpec.type)
349 {
350 case TEXTURETYPE_2D:
351 {
352 float cStep = 1.0f / (float)de::max(1, m_textureSpec.numLevels - 1);
353 Vec4 cScale = fmtInfo.valueMax - fmtInfo.valueMin;
354 Vec4 cBias = fmtInfo.valueMin;
355 int baseCellSize = de::min(m_textureSpec.width / 4, m_textureSpec.height / 4);
356
357 m_texture2D = new glu::Texture2D(m_renderCtx, m_textureSpec.format, m_textureSpec.dataType, m_textureSpec.width,
358 m_textureSpec.height);
359 for (int level = 0; level < m_textureSpec.numLevels; level++)
360 {
361 float fA = float(level) * cStep;
362 float fB = 1.0f - fA;
363 Vec4 colorA = cBias + cScale * Vec4(fA, fB, fA, fB);
364 Vec4 colorB = cBias + cScale * Vec4(fB, fA, fB, fA);
365
366 m_texture2D->getRefTexture().allocLevel(level);
367 tcu::fillWithGrid(m_texture2D->getRefTexture().getLevel(level), de::max(1, baseCellSize >> level), colorA,
368 colorB);
369 }
370 m_texture2D->upload();
371
372 // Compute LOD.
373 float dudx = (m_lookupSpec.maxCoord[0] - m_lookupSpec.minCoord[0]) * proj * (float)m_textureSpec.width /
374 (float)viewportSize[0];
375 float dvdy = (m_lookupSpec.maxCoord[1] - m_lookupSpec.minCoord[1]) * proj * (float)m_textureSpec.height /
376 (float)viewportSize[1];
377 m_lookupParams.lod =
378 glu::TextureTestUtil::computeLodFromDerivates(glu::TextureTestUtil::LODMODE_EXACT, dudx, 0.0f, 0.0f, dvdy);
379
380 // Append to texture list.
381 m_textures.push_back(gls::TextureBinding(m_texture2D, m_textureSpec.sampler));
382 break;
383 }
384
385 case TEXTURETYPE_CUBE_MAP:
386 {
387 float cStep = 1.0f / (float)de::max(1, m_textureSpec.numLevels - 1);
388 Vec4 cScale = fmtInfo.valueMax - fmtInfo.valueMin;
389 Vec4 cBias = fmtInfo.valueMin;
390 int baseCellSize = de::min(m_textureSpec.width / 4, m_textureSpec.height / 4);
391
392 DE_ASSERT(m_textureSpec.width == m_textureSpec.height);
393 m_textureCube =
394 new glu::TextureCube(m_renderCtx, m_textureSpec.format, m_textureSpec.dataType, m_textureSpec.width);
395 for (int level = 0; level < m_textureSpec.numLevels; level++)
396 {
397 float fA = float(level) * cStep;
398 float fB = 1.0f - fA;
399 Vec2 f(fA, fB);
400
401 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
402 {
403 const IVec4 &swzA = texCubeSwz[face];
404 IVec4 swzB = 1 - swzA;
405 Vec4 colorA = cBias + cScale * f.swizzle(swzA[0], swzA[1], swzA[2], swzA[3]);
406 Vec4 colorB = cBias + cScale * f.swizzle(swzB[0], swzB[1], swzB[2], swzB[3]);
407
408 m_textureCube->getRefTexture().allocLevel((tcu::CubeFace)face, level);
409 tcu::fillWithGrid(m_textureCube->getRefTexture().getLevelFace(level, (tcu::CubeFace)face),
410 de::max(1, baseCellSize >> level), colorA, colorB);
411 }
412 }
413 m_textureCube->upload();
414
415 // Compute LOD \note Assumes that only single side is accessed and R is constant major axis.
416 DE_ASSERT(de::abs(m_lookupSpec.minCoord[2] - m_lookupSpec.maxCoord[2]) < 0.005);
417 DE_ASSERT(de::abs(m_lookupSpec.minCoord[0]) < de::abs(m_lookupSpec.minCoord[2]) &&
418 de::abs(m_lookupSpec.maxCoord[0]) < de::abs(m_lookupSpec.minCoord[2]));
419 DE_ASSERT(de::abs(m_lookupSpec.minCoord[1]) < de::abs(m_lookupSpec.minCoord[2]) &&
420 de::abs(m_lookupSpec.maxCoord[1]) < de::abs(m_lookupSpec.minCoord[2]));
421
422 tcu::CubeFaceFloatCoords c00 = tcu::getCubeFaceCoords(
423 Vec3(m_lookupSpec.minCoord[0] * proj, m_lookupSpec.minCoord[1] * proj, m_lookupSpec.minCoord[2] * proj));
424 tcu::CubeFaceFloatCoords c10 = tcu::getCubeFaceCoords(
425 Vec3(m_lookupSpec.maxCoord[0] * proj, m_lookupSpec.minCoord[1] * proj, m_lookupSpec.minCoord[2] * proj));
426 tcu::CubeFaceFloatCoords c01 = tcu::getCubeFaceCoords(
427 Vec3(m_lookupSpec.minCoord[0] * proj, m_lookupSpec.maxCoord[1] * proj, m_lookupSpec.minCoord[2] * proj));
428 float dudx = (c10.s - c00.s) * (float)m_textureSpec.width / (float)viewportSize[0];
429 float dvdy = (c01.t - c00.t) * (float)m_textureSpec.height / (float)viewportSize[1];
430
431 m_lookupParams.lod =
432 glu::TextureTestUtil::computeLodFromDerivates(glu::TextureTestUtil::LODMODE_EXACT, dudx, 0.0f, 0.0f, dvdy);
433
434 m_textures.push_back(gls::TextureBinding(m_textureCube, m_textureSpec.sampler));
435 break;
436 }
437
438 default:
439 DE_ASSERT(false);
440 }
441
442 // Set lookup scale & bias
443 m_lookupParams.scale = fmtInfo.lookupScale;
444 m_lookupParams.bias = fmtInfo.lookupBias;
445 }
446
initShaderSources(void)447 void ShaderTextureFunctionCase::initShaderSources(void)
448 {
449 Function function = m_lookupSpec.function;
450 bool isVtxCase = m_isVertexCase;
451 bool isProj = functionHasProj(function);
452 bool is2DProj4 = m_textureSpec.type == TEXTURETYPE_2D &&
453 (function == FUNCTION_TEXTUREPROJ || function == FUNCTION_TEXTUREPROJLOD);
454 bool hasLodBias = functionHasLod(m_lookupSpec.function) || m_lookupSpec.useBias;
455 int texCoordComps = m_textureSpec.type == TEXTURETYPE_2D ? 2 : 3;
456 int extraCoordComps = isProj ? (is2DProj4 ? 2 : 1) : 0;
457 glu::DataType coordType = glu::getDataTypeFloatVec(texCoordComps + extraCoordComps);
458 glu::Precision coordPrec = glu::PRECISION_MEDIUMP;
459 const char *coordTypeName = glu::getDataTypeName(coordType);
460 const char *coordPrecName = glu::getPrecisionName(coordPrec);
461 tcu::TextureFormat texFmt = glu::mapGLTransferFormat(m_textureSpec.format, m_textureSpec.dataType);
462 glu::DataType samplerType = glu::TYPE_LAST;
463 const char *baseFuncName = m_textureSpec.type == TEXTURETYPE_2D ? "texture2D" : "textureCube";
464 const char *funcExt = DE_NULL;
465
466 switch (m_textureSpec.type)
467 {
468 case TEXTURETYPE_2D:
469 samplerType = glu::getSampler2DType(texFmt);
470 break;
471 case TEXTURETYPE_CUBE_MAP:
472 samplerType = glu::getSamplerCubeType(texFmt);
473 break;
474 default:
475 DE_ASSERT(false);
476 }
477
478 switch (m_lookupSpec.function)
479 {
480 case FUNCTION_TEXTURE:
481 funcExt = "";
482 break;
483 case FUNCTION_TEXTUREPROJ:
484 funcExt = "Proj";
485 break;
486 case FUNCTION_TEXTUREPROJ3:
487 funcExt = "Proj";
488 break;
489 case FUNCTION_TEXTURELOD:
490 funcExt = "Lod";
491 break;
492 case FUNCTION_TEXTUREPROJLOD:
493 funcExt = "ProjLod";
494 break;
495 case FUNCTION_TEXTUREPROJLOD3:
496 funcExt = "ProjLod";
497 break;
498 default:
499 DE_ASSERT(false);
500 }
501
502 std::ostringstream vert;
503 std::ostringstream frag;
504 std::ostringstream &op = isVtxCase ? vert : frag;
505
506 vert << "attribute highp vec4 a_position;\n"
507 << "attribute " << coordPrecName << " " << coordTypeName << " a_in0;\n";
508
509 if (hasLodBias)
510 vert << "attribute " << coordPrecName << " float a_in1;\n";
511
512 if (isVtxCase)
513 {
514 vert << "varying mediump vec4 v_color;\n";
515 frag << "varying mediump vec4 v_color;\n";
516 }
517 else
518 {
519 vert << "varying " << coordPrecName << " " << coordTypeName << " v_texCoord;\n";
520 frag << "varying " << coordPrecName << " " << coordTypeName << " v_texCoord;\n";
521
522 if (hasLodBias)
523 {
524 vert << "varying " << coordPrecName << " float v_lodBias;\n";
525 frag << "varying " << coordPrecName << " float v_lodBias;\n";
526 }
527 }
528
529 // Uniforms
530 op << "uniform lowp " << glu::getDataTypeName(samplerType) << " u_sampler;\n";
531
532 vert << "\nvoid main()\n{\n"
533 << "\tgl_Position = a_position;\n";
534 frag << "\nvoid main()\n{\n";
535
536 if (isVtxCase)
537 vert << "\tv_color = ";
538 else
539 frag << "\tgl_FragColor = ";
540
541 // Op.
542 {
543 const char *texCoord = isVtxCase ? "a_in0" : "v_texCoord";
544 const char *lodBias = isVtxCase ? "a_in1" : "v_lodBias";
545
546 op << baseFuncName << funcExt;
547 op << "(u_sampler, " << texCoord;
548
549 if (functionHasLod(function) || m_lookupSpec.useBias)
550 op << ", " << lodBias;
551
552 op << ");\n";
553 }
554
555 if (isVtxCase)
556 frag << "\tgl_FragColor = v_color;\n";
557 else
558 {
559 vert << "\tv_texCoord = a_in0;\n";
560
561 if (hasLodBias)
562 vert << "\tv_lodBias = a_in1;\n";
563 }
564
565 vert << "}\n";
566 frag << "}\n";
567
568 m_vertShaderSource = vert.str();
569 m_fragShaderSource = frag.str();
570 }
571
deinit(void)572 void ShaderTextureFunctionCase::deinit(void)
573 {
574 gls::ShaderRenderCase::deinit();
575
576 delete m_texture2D;
577 delete m_textureCube;
578
579 m_texture2D = DE_NULL;
580 m_textureCube = DE_NULL;
581 }
582
setupUniforms(int programID,const tcu::Vec4 &)583 void ShaderTextureFunctionCase::setupUniforms(int programID, const tcu::Vec4 &)
584 {
585 const glw::Functions &gl = m_renderCtx.getFunctions();
586 gl.uniform1i(gl.getUniformLocation(programID, "u_sampler"), 0);
587 }
588
ShaderTextureFunctionTests(Context & context)589 ShaderTextureFunctionTests::ShaderTextureFunctionTests(Context &context)
590 : TestCaseGroup(context, "texture_functions", "Texture Access Function Tests")
591 {
592 }
593
~ShaderTextureFunctionTests(void)594 ShaderTextureFunctionTests::~ShaderTextureFunctionTests(void)
595 {
596 }
597
598 struct TexFuncCaseSpec
599 {
600 const char *name;
601 TextureLookupSpec lookupSpec;
602 TextureSpec texSpec;
603 TexEvalFunc evalFunc;
604 };
605
606 #define CASE_SPEC(NAME, FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD, TEXSPEC, EVALFUNC) \
607 { \
608 #NAME, TextureLookupSpec(FUNC, MINCOORD, MAXCOORD, USEBIAS, MINLOD, MAXLOD), TEXSPEC, EVALFUNC \
609 }
610
createCaseGroup(TestCaseGroup * parent,const char * groupName,const char * groupDesc,const TexFuncCaseSpec * cases,int numCases,bool isVertex)611 static void createCaseGroup(TestCaseGroup *parent, const char *groupName, const char *groupDesc,
612 const TexFuncCaseSpec *cases, int numCases, bool isVertex)
613 {
614 tcu::TestCaseGroup *group = new tcu::TestCaseGroup(parent->getTestContext(), groupName, groupDesc);
615 parent->addChild(group);
616
617 for (int ndx = 0; ndx < numCases; ndx++)
618 group->addChild(new ShaderTextureFunctionCase(parent->getContext(), cases[ndx].name, "", cases[ndx].lookupSpec,
619 cases[ndx].texSpec, cases[ndx].evalFunc, isVertex));
620 }
621
init(void)622 void ShaderTextureFunctionTests::init(void)
623 {
624 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
625
626 // Samplers
627 static const tcu::Sampler samplerLinearNoMipmap(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
628 tcu::Sampler::REPEAT_GL, tcu::Sampler::LINEAR,
629 tcu::Sampler::LINEAR);
630 static tcu::Sampler samplerLinearMipmap(tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
631 tcu::Sampler::LINEAR_MIPMAP_NEAREST, tcu::Sampler::LINEAR);
632
633 samplerLinearMipmap.seamlessCubeMap = glu::IsES3Compatible(gl);
634
635 // Default textures.
636 // Type Format DataType W H L Sampler
637 static const TextureSpec tex2D(TEXTURETYPE_2D, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 1, samplerLinearNoMipmap);
638 static const TextureSpec tex2DMipmap(TEXTURETYPE_2D, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 9, samplerLinearMipmap);
639
640 static const TextureSpec texCube(TEXTURETYPE_CUBE_MAP, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 1,
641 samplerLinearNoMipmap);
642 static const TextureSpec texCubeMipmap(TEXTURETYPE_CUBE_MAP, GL_RGBA, GL_UNSIGNED_BYTE, 256, 256, 9,
643 samplerLinearMipmap);
644
645 // Vertex cases
646 static const TexFuncCaseSpec vertexCases[] = {
647 // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Texture EvalFunc
648 CASE_SPEC(texture2d, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4(1.5f, 2.3f, 0.0f, 0.0f), false,
649 0.0f, 0.0f, tex2D, evalTexture2D),
650 // 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),
651 CASE_SPEC(texture2dproj_vec3, FUNCTION_TEXTUREPROJ3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f),
652 Vec4(2.25f, 3.45f, 1.5f, 0.0f), false, 0.0f, 0.0f, tex2D, evalTexture2DProj3),
653 CASE_SPEC(texture2dproj_vec4, FUNCTION_TEXTUREPROJ, Vec4(-0.3f, -0.6f, 0.0f, 1.5f),
654 Vec4(2.25f, 3.45f, 0.0f, 1.5f), false, 0.0f, 0.0f, tex2D, evalTexture2DProj),
655 CASE_SPEC(texture2dlod, FUNCTION_TEXTURELOD, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4(1.5f, 2.3f, 0.0f, 0.0f),
656 false, -1.0f, 9.0f, tex2DMipmap, evalTexture2DLod),
657 // 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),
658 // 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),
659 CASE_SPEC(texture2dprojlod_vec3, FUNCTION_TEXTUREPROJLOD3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f),
660 Vec4(2.25f, 3.45f, 1.5f, 0.0f), false, -1.0f, 9.0f, tex2D, evalTexture2DProjLod3),
661 CASE_SPEC(texture2dprojlod_vec4, FUNCTION_TEXTUREPROJLOD, Vec4(-0.3f, -0.6f, 0.0f, 1.5f),
662 Vec4(2.25f, 3.45f, 0.0f, 1.5f), false, -1.0f, 9.0f, tex2D, evalTexture2DProjLod),
663 CASE_SPEC(texturecube, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4(1.0f, 1.0f, 1.01f, 0.0f), false,
664 0.0f, 0.0f, texCube, evalTextureCube),
665 // 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),
666 CASE_SPEC(texturecubelod, FUNCTION_TEXTURELOD, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4(1.0f, 1.0f, 1.01f, 0.0f),
667 false, -1.0f, 9.0f, texCubeMipmap, evalTextureCubeLod),
668 };
669 createCaseGroup(this, "vertex", "Vertex Shader Texture Lookups", &vertexCases[0], DE_LENGTH_OF_ARRAY(vertexCases),
670 true);
671
672 // Fragment cases
673 static const TexFuncCaseSpec fragmentCases[] = {
674 // Name Function MinCoord MaxCoord Bias? MinLod MaxLod Texture EvalFunc
675 CASE_SPEC(texture2d, FUNCTION_TEXTURE, Vec4(-0.2f, -0.4f, 0.0f, 0.0f), Vec4(1.5f, 2.3f, 0.0f, 0.0f), false,
676 0.0f, 0.0f, tex2DMipmap, evalTexture2D),
677 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,
678 -2.0f, 2.0f, tex2DMipmap, evalTexture2DBias),
679 CASE_SPEC(texture2dproj_vec3, FUNCTION_TEXTUREPROJ3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f),
680 Vec4(2.25f, 3.45f, 1.5f, 0.0f), false, 0.0f, 0.0f, tex2DMipmap, evalTexture2DProj3),
681 CASE_SPEC(texture2dproj_vec4, FUNCTION_TEXTUREPROJ, Vec4(-0.3f, -0.6f, 0.0f, 1.5f),
682 Vec4(2.25f, 3.45f, 0.0f, 1.5f), false, 0.0f, 0.0f, tex2DMipmap, evalTexture2DProj),
683 CASE_SPEC(texture2dproj_vec3_bias, FUNCTION_TEXTUREPROJ3, Vec4(-0.3f, -0.6f, 1.5f, 0.0f),
684 Vec4(2.25f, 3.45f, 1.5f, 0.0f), true, -2.0f, 2.0f, tex2DMipmap, evalTexture2DProj3Bias),
685 CASE_SPEC(texture2dproj_vec4_bias, FUNCTION_TEXTUREPROJ, Vec4(-0.3f, -0.6f, 0.0f, 1.5f),
686 Vec4(2.25f, 3.45f, 0.0f, 1.5f), true, -2.0f, 2.0f, tex2DMipmap, evalTexture2DProjBias),
687 CASE_SPEC(texturecube, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, 1.01f, 0.0f), Vec4(1.0f, 1.0f, 1.01f, 0.0f), false,
688 0.0f, 0.0f, texCubeMipmap, evalTextureCube),
689 CASE_SPEC(texturecube_bias, FUNCTION_TEXTURE, Vec4(-1.0f, -1.0f, -1.01f, 0.0f), Vec4(1.0f, 1.0f, -1.01f, 0.0f),
690 true, -2.0f, 2.0f, texCubeMipmap, evalTextureCubeBias)};
691 createCaseGroup(this, "fragment", "Fragment Shader Texture Lookups", &fragmentCases[0],
692 DE_LENGTH_OF_ARRAY(fragmentCases), false);
693
694 // Negative cases.
695 {
696 gls::ShaderLibrary library(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo());
697 std::vector<tcu::TestNode *> negativeCases = library.loadShaderFile("shaders/invalid_texture_functions.test");
698
699 tcu::TestCaseGroup *group =
700 new tcu::TestCaseGroup(m_testCtx, "invalid", "Invalid texture function usage", negativeCases);
701 addChild(group);
702 }
703 }
704
705 } // namespace Functional
706 } // namespace gles2
707 } // namespace deqp
708