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