7e4bd10dc6ad6cfdf2195ff5a5f3fa9ceceda6ff
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / shaderrender / vktShaderRenderTextureGatherTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
7  * Copyright (c) 2016 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief GLSL textureGather[Offset[s]] tests.
24  *//*--------------------------------------------------------------------*/
25
26 #include "vktShaderRenderTextureGatherTests.hpp"
27 #include "vktShaderRender.hpp"
28 #include "vkImageUtil.hpp"
29 #include "gluTextureUtil.hpp"
30 #include "tcuTexture.hpp"
31 #include "tcuTextureUtil.hpp"
32 #include "tcuSurface.hpp"
33 #include "tcuTestLog.hpp"
34 #include "tcuVectorUtil.hpp"
35 #include "tcuTexLookupVerifier.hpp"
36 #include "tcuTexCompareVerifier.hpp"
37 #include "tcuPixelFormat.hpp"
38 #include "tcuCommandLine.hpp"
39 #include "deUniquePtr.hpp"
40 #include "deStringUtil.hpp"
41 #include "deRandom.hpp"
42
43 using tcu::ConstPixelBufferAccess;
44 using tcu::PixelBufferAccess;
45 using tcu::TestLog;
46 using tcu::IVec2;
47 using tcu::IVec3;
48 using tcu::IVec4;
49 using tcu::UVec4;
50 using tcu::Vec2;
51 using tcu::Vec3;
52 using tcu::Vec4;
53 using de::MovePtr;
54
55 using std::string;
56 using std::vector;
57
58 namespace vkt
59 {
60 namespace sr
61 {
62 namespace
63 {
64
65 typedef ShaderRenderCaseInstance::ImageBackingMode ImageBackingMode;
66
67 enum
68 {
69         SPEC_MAX_MIN_OFFSET = -8,
70         SPEC_MIN_MAX_OFFSET = 7
71 };
72
73 enum TextureType
74 {
75         TEXTURETYPE_2D,
76         TEXTURETYPE_2D_ARRAY,
77         TEXTURETYPE_CUBE,
78
79         TEXTURETYPE_LAST
80 };
81
82 // \note TextureTestUtil functions are copied from glsTextureTestUtil
83 namespace TextureTestUtil
84 {
85
86 inline tcu::IVec4 getBitsVec (const tcu::PixelFormat& format)
87 {
88         return tcu::IVec4(format.redBits, format.greenBits, format.blueBits, format.alphaBits);
89 }
90
91 inline tcu::BVec4 getCompareMask (const tcu::PixelFormat& format)
92 {
93         return tcu::BVec4(format.redBits        > 0,
94                                           format.greenBits      > 0,
95                                           format.blueBits       > 0,
96                                           format.alphaBits      > 0);
97 }
98
99 void computeQuadTexCoord2D (std::vector<float>& dst, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
100 {
101         dst.resize(4*2);
102
103         dst[0] = bottomLeft.x();        dst[1] = bottomLeft.y();
104         dst[2] = bottomLeft.x();        dst[3] = topRight.y();
105         dst[4] = topRight.x();          dst[5] = bottomLeft.y();
106         dst[6] = topRight.x();          dst[7] = topRight.y();
107 }
108
109 void computeQuadTexCoord2DArray (std::vector<float>& dst, int layerNdx, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
110 {
111         dst.resize(4*3);
112
113         dst[0] = bottomLeft.x();        dst[ 1] = bottomLeft.y();       dst[ 2] = (float)layerNdx;
114         dst[3] = bottomLeft.x();        dst[ 4] = topRight.y();         dst[ 5] = (float)layerNdx;
115         dst[6] = topRight.x();          dst[ 7] = bottomLeft.y();       dst[ 8] = (float)layerNdx;
116         dst[9] = topRight.x();          dst[10] = topRight.y();         dst[11] = (float)layerNdx;
117 }
118
119 void computeQuadTexCoordCube (std::vector<float>& dst, tcu::CubeFace face, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
120 {
121         int             sRow            = 0;
122         int             tRow            = 0;
123         int             mRow            = 0;
124         float   sSign           = 1.0f;
125         float   tSign           = 1.0f;
126         float   mSign           = 1.0f;
127
128         switch (face)
129         {
130                 case tcu::CUBEFACE_NEGATIVE_X: mRow = 0; sRow = 2; tRow = 1; mSign = -1.0f;                                tSign = -1.0f;       break;
131                 case tcu::CUBEFACE_POSITIVE_X: mRow = 0; sRow = 2; tRow = 1;                            sSign = -1.0f; tSign = -1.0f;   break;
132                 case tcu::CUBEFACE_NEGATIVE_Y: mRow = 1; sRow = 0; tRow = 2; mSign = -1.0f;                                tSign = -1.0f;       break;
133                 case tcu::CUBEFACE_POSITIVE_Y: mRow = 1; sRow = 0; tRow = 2;                                                                                            break;
134                 case tcu::CUBEFACE_NEGATIVE_Z: mRow = 2; sRow = 0; tRow = 1; mSign = -1.0f; sSign = -1.0f; tSign = -1.0f;       break;
135                 case tcu::CUBEFACE_POSITIVE_Z: mRow = 2; sRow = 0; tRow = 1;                                                       tSign = -1.0f;       break;
136                 default:
137                         DE_ASSERT(DE_FALSE);
138                         return;
139         }
140
141         dst.resize(3*4);
142
143         dst[0+mRow] = mSign;
144         dst[3+mRow] = mSign;
145         dst[6+mRow] = mSign;
146         dst[9+mRow] = mSign;
147
148         dst[0+sRow] = sSign * bottomLeft.x();
149         dst[3+sRow] = sSign * bottomLeft.x();
150         dst[6+sRow] = sSign * topRight.x();
151         dst[9+sRow] = sSign * topRight.x();
152
153         dst[0+tRow] = tSign * bottomLeft.y();
154         dst[3+tRow] = tSign * topRight.y();
155         dst[6+tRow] = tSign * bottomLeft.y();
156         dst[9+tRow] = tSign * topRight.y();
157 }
158
159 } // TextureTestUtil
160
161 // Round-to-zero int division, because pre-c++11 it's somewhat implementation-defined for negative values.
162 static inline int divRoundToZero (int a, int b)
163 {
164         return de::abs(a) / de::abs(b) * deSign32(a) * deSign32(b);
165 }
166
167 static void fillWithRandomColorTiles (const PixelBufferAccess& dst, const Vec4& minVal, const Vec4& maxVal, deUint32 seed)
168 {
169         const int       numCols         = dst.getWidth()  >= 7 ? 7 : dst.getWidth();
170         const int       numRows         = dst.getHeight() >= 5 ? 5 : dst.getHeight();
171         de::Random      rnd                     (seed);
172
173         for (int slice = 0; slice < dst.getDepth(); slice++)
174         for (int row = 0; row < numRows; row++)
175         for (int col = 0; col < numCols; col++)
176         {
177                 const int       yBegin  = (row+0)*dst.getHeight()/numRows;
178                 const int       yEnd    = (row+1)*dst.getHeight()/numRows;
179                 const int       xBegin  = (col+0)*dst.getWidth()/numCols;
180                 const int       xEnd    = (col+1)*dst.getWidth()/numCols;
181                 Vec4            color;
182                 for (int i = 0; i < 4; i++)
183                         color[i] = rnd.getFloat(minVal[i], maxVal[i]);
184                 tcu::clear(tcu::getSubregion(dst, xBegin, yBegin, slice, xEnd-xBegin, yEnd-yBegin, 1), color);
185         }
186 }
187
188 static inline bool isDepthFormat (const tcu::TextureFormat& fmt)
189 {
190         return fmt.order == tcu::TextureFormat::D || fmt.order == tcu::TextureFormat::DS;
191 }
192
193 static inline bool isUnormFormatType (tcu::TextureFormat::ChannelType type)
194 {
195         return type == tcu::TextureFormat::UNORM_INT8   ||
196                    type == tcu::TextureFormat::UNORM_INT16      ||
197                    type == tcu::TextureFormat::UNORM_INT32;
198 }
199
200 static inline bool isSIntFormatType (tcu::TextureFormat::ChannelType type)
201 {
202         return type == tcu::TextureFormat::SIGNED_INT8  ||
203                    type == tcu::TextureFormat::SIGNED_INT16     ||
204                    type == tcu::TextureFormat::SIGNED_INT32;
205 }
206
207 static inline bool isUIntFormatType (tcu::TextureFormat::ChannelType type)
208 {
209         return type == tcu::TextureFormat::UNSIGNED_INT8        ||
210                    type == tcu::TextureFormat::UNSIGNED_INT16   ||
211                    type == tcu::TextureFormat::UNSIGNED_INT32;
212 }
213
214 enum TextureSwizzleComponent
215 {
216         TEXTURESWIZZLECOMPONENT_R = 0,
217         TEXTURESWIZZLECOMPONENT_G,
218         TEXTURESWIZZLECOMPONENT_B,
219         TEXTURESWIZZLECOMPONENT_A,
220         TEXTURESWIZZLECOMPONENT_ZERO,
221         TEXTURESWIZZLECOMPONENT_ONE,
222
223         TEXTURESWIZZLECOMPONENT_LAST
224 };
225
226 static std::ostream& operator<< (std::ostream& stream, TextureSwizzleComponent comp)
227 {
228         switch (comp)
229         {
230                 case TEXTURESWIZZLECOMPONENT_R:         return stream << "RED";
231                 case TEXTURESWIZZLECOMPONENT_G:         return stream << "GREEN";
232                 case TEXTURESWIZZLECOMPONENT_B:         return stream << "BLUE";
233                 case TEXTURESWIZZLECOMPONENT_A:         return stream << "ALPHA";
234                 case TEXTURESWIZZLECOMPONENT_ZERO:      return stream << "ZERO";
235                 case TEXTURESWIZZLECOMPONENT_ONE:       return stream << "ONE";
236                 default: DE_ASSERT(false); return stream;
237         }
238 }
239
240 struct MaybeTextureSwizzle
241 {
242 public:
243         static MaybeTextureSwizzle                                              createNoneTextureSwizzle        (void);
244         static MaybeTextureSwizzle                                              createSomeTextureSwizzle        (void);
245
246         bool                                                                                    isSome                                          (void) const;
247         bool                                                                                    isNone                                          (void) const;
248         bool                                                                                    isIdentitySwizzle                       (void) const;
249
250         tcu::Vector<TextureSwizzleComponent, 4>&                getSwizzle                                      (void);
251         const tcu::Vector<TextureSwizzleComponent, 4>&  getSwizzle                                      (void) const;
252
253 private:
254                                                                                                         MaybeTextureSwizzle                     (void);
255
256         tcu::Vector<TextureSwizzleComponent, 4>                 m_swizzle;
257         bool                                                                                    m_isSome;
258 };
259
260 static std::ostream& operator<< (std::ostream& stream, const MaybeTextureSwizzle& comp)
261 {
262         if (comp.isNone())
263                 stream << "[default swizzle state]";
264         else
265                 stream << "(" << comp.getSwizzle()[0]
266                            << ", " << comp.getSwizzle()[1]
267                            << ", " << comp.getSwizzle()[2]
268                            << ", " << comp.getSwizzle()[3]
269                            << ")";
270
271         return stream;
272 }
273
274 MaybeTextureSwizzle MaybeTextureSwizzle::createNoneTextureSwizzle (void)
275 {
276         MaybeTextureSwizzle swizzle;
277
278         swizzle.m_swizzle[0] = TEXTURESWIZZLECOMPONENT_LAST;
279         swizzle.m_swizzle[1] = TEXTURESWIZZLECOMPONENT_LAST;
280         swizzle.m_swizzle[2] = TEXTURESWIZZLECOMPONENT_LAST;
281         swizzle.m_swizzle[3] = TEXTURESWIZZLECOMPONENT_LAST;
282         swizzle.m_isSome = false;
283
284         return swizzle;
285 }
286
287 MaybeTextureSwizzle MaybeTextureSwizzle::createSomeTextureSwizzle (void)
288 {
289         MaybeTextureSwizzle swizzle;
290
291         swizzle.m_swizzle[0] = TEXTURESWIZZLECOMPONENT_R;
292         swizzle.m_swizzle[1] = TEXTURESWIZZLECOMPONENT_G;
293         swizzle.m_swizzle[2] = TEXTURESWIZZLECOMPONENT_B;
294         swizzle.m_swizzle[3] = TEXTURESWIZZLECOMPONENT_A;
295         swizzle.m_isSome = true;
296
297         return swizzle;
298 }
299
300 bool MaybeTextureSwizzle::isSome (void) const
301 {
302         return m_isSome;
303 }
304
305 bool MaybeTextureSwizzle::isNone (void) const
306 {
307         return !m_isSome;
308 }
309
310 bool MaybeTextureSwizzle::isIdentitySwizzle (void) const
311 {
312         return  m_isSome                                                                        &&
313                         m_swizzle[0] == TEXTURESWIZZLECOMPONENT_R       &&
314                         m_swizzle[1] == TEXTURESWIZZLECOMPONENT_G       &&
315                         m_swizzle[2] == TEXTURESWIZZLECOMPONENT_B       &&
316                         m_swizzle[3] == TEXTURESWIZZLECOMPONENT_A;
317 }
318
319 tcu::Vector<TextureSwizzleComponent, 4>& MaybeTextureSwizzle::getSwizzle (void)
320 {
321         return m_swizzle;
322 }
323
324 const tcu::Vector<TextureSwizzleComponent, 4>& MaybeTextureSwizzle::getSwizzle (void) const
325 {
326         return m_swizzle;
327 }
328
329 MaybeTextureSwizzle::MaybeTextureSwizzle (void)
330         : m_swizzle     (TEXTURESWIZZLECOMPONENT_LAST, TEXTURESWIZZLECOMPONENT_LAST, TEXTURESWIZZLECOMPONENT_LAST, TEXTURESWIZZLECOMPONENT_LAST)
331         , m_isSome      (false)
332 {
333 }
334
335 static vk::VkComponentSwizzle getTextureSwizzleComponent (TextureSwizzleComponent c)
336 {
337         switch (c)
338         {
339                 case TEXTURESWIZZLECOMPONENT_R:         return vk::VK_COMPONENT_SWIZZLE_R;
340                 case TEXTURESWIZZLECOMPONENT_G:         return vk::VK_COMPONENT_SWIZZLE_G;
341                 case TEXTURESWIZZLECOMPONENT_B:         return vk::VK_COMPONENT_SWIZZLE_B;
342                 case TEXTURESWIZZLECOMPONENT_A:         return vk::VK_COMPONENT_SWIZZLE_A;
343                 case TEXTURESWIZZLECOMPONENT_ZERO:      return vk::VK_COMPONENT_SWIZZLE_ZERO;
344                 case TEXTURESWIZZLECOMPONENT_ONE:       return vk::VK_COMPONENT_SWIZZLE_ONE;
345                 default: DE_ASSERT(false); return (vk::VkComponentSwizzle)0;
346         }
347 }
348
349 template <typename T>
350 static inline T swizzleColorChannel (const tcu::Vector<T, 4>& src, TextureSwizzleComponent swizzle)
351 {
352         switch (swizzle)
353         {
354                 case TEXTURESWIZZLECOMPONENT_R:         return src[0];
355                 case TEXTURESWIZZLECOMPONENT_G:         return src[1];
356                 case TEXTURESWIZZLECOMPONENT_B:         return src[2];
357                 case TEXTURESWIZZLECOMPONENT_A:         return src[3];
358                 case TEXTURESWIZZLECOMPONENT_ZERO:      return (T)0;
359                 case TEXTURESWIZZLECOMPONENT_ONE:       return (T)1;
360                 default: DE_ASSERT(false); return (T)-1;
361         }
362 }
363
364 template <typename T>
365 static inline tcu::Vector<T, 4> swizzleColor (const tcu::Vector<T, 4>& src, const MaybeTextureSwizzle& swizzle)
366 {
367         DE_ASSERT(swizzle.isSome());
368
369         tcu::Vector<T, 4> result;
370         for (int i = 0; i < 4; i++)
371                 result[i] = swizzleColorChannel(src, swizzle.getSwizzle()[i]);
372         return result;
373 }
374
375 template <typename T>
376 static void swizzlePixels (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src, const MaybeTextureSwizzle& swizzle)
377 {
378         DE_ASSERT(dst.getWidth()  == src.getWidth()  &&
379                           dst.getHeight() == src.getHeight() &&
380                           dst.getDepth()  == src.getDepth());
381         for (int z = 0; z < src.getDepth(); z++)
382         for (int y = 0; y < src.getHeight(); y++)
383         for (int x = 0; x < src.getWidth(); x++)
384                 dst.setPixel(swizzleColor(src.getPixelT<T>(x, y, z), swizzle), x, y, z);
385 }
386
387 static void swizzlePixels (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src, const MaybeTextureSwizzle& swizzle)
388 {
389         if (isDepthFormat(dst.getFormat()))
390                 DE_ASSERT(swizzle.isNone() || swizzle.isIdentitySwizzle());
391
392         if (swizzle.isNone() || swizzle.isIdentitySwizzle())
393                 tcu::copy(dst, src);
394         else if (isUnormFormatType(dst.getFormat().type))
395                 swizzlePixels<float>(dst, src, swizzle);
396         else if (isUIntFormatType(dst.getFormat().type))
397                 swizzlePixels<deUint32>(dst, src, swizzle);
398         else if (isSIntFormatType(dst.getFormat().type))
399                 swizzlePixels<deInt32>(dst, src, swizzle);
400         else
401                 DE_ASSERT(false);
402 }
403
404 static void swizzleTexture (tcu::Texture2D& dst, const tcu::Texture2D& src, const MaybeTextureSwizzle& swizzle)
405 {
406         dst = tcu::Texture2D(src.getFormat(), src.getWidth(), src.getHeight());
407         for (int levelNdx = 0; levelNdx < src.getNumLevels(); levelNdx++)
408         {
409                 if (src.isLevelEmpty(levelNdx))
410                         continue;
411                 dst.allocLevel(levelNdx);
412                 swizzlePixels(dst.getLevel(levelNdx), src.getLevel(levelNdx), swizzle);
413         }
414 }
415
416 static void swizzleTexture (tcu::Texture2DArray& dst, const tcu::Texture2DArray& src, const MaybeTextureSwizzle& swizzle)
417 {
418         dst = tcu::Texture2DArray(src.getFormat(), src.getWidth(), src.getHeight(), src.getNumLayers());
419         for (int levelNdx = 0; levelNdx < src.getNumLevels(); levelNdx++)
420         {
421                 if (src.isLevelEmpty(levelNdx))
422                         continue;
423                 dst.allocLevel(levelNdx);
424                 swizzlePixels(dst.getLevel(levelNdx), src.getLevel(levelNdx), swizzle);
425         }
426 }
427
428 static void swizzleTexture (tcu::TextureCube& dst, const tcu::TextureCube& src, const MaybeTextureSwizzle& swizzle)
429 {
430         dst = tcu::TextureCube(src.getFormat(), src.getSize());
431         for (int faceI = 0; faceI < tcu::CUBEFACE_LAST; faceI++)
432         {
433                 const tcu::CubeFace face = (tcu::CubeFace)faceI;
434                 for (int levelNdx = 0; levelNdx < src.getNumLevels(); levelNdx++)
435                 {
436                         if (src.isLevelEmpty(face, levelNdx))
437                                 continue;
438                         dst.allocLevel(face, levelNdx);
439                         swizzlePixels(dst.getLevelFace(levelNdx, face), src.getLevelFace(levelNdx, face), swizzle);
440                 }
441         }
442 }
443
444 static tcu::Texture2DView getOneLevelSubView (const tcu::Texture2DView& view, int level)
445 {
446         return tcu::Texture2DView(1, view.getLevels() + level);
447 }
448
449 static tcu::Texture2DArrayView getOneLevelSubView (const tcu::Texture2DArrayView& view, int level)
450 {
451         return tcu::Texture2DArrayView(1, view.getLevels() + level);
452 }
453
454 static tcu::TextureCubeView getOneLevelSubView (const tcu::TextureCubeView& view, int level)
455 {
456         const tcu::ConstPixelBufferAccess* levels[tcu::CUBEFACE_LAST];
457
458         for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
459                 levels[face] = view.getFaceLevels((tcu::CubeFace)face) + level;
460
461         return tcu::TextureCubeView(1, levels);
462 }
463
464 class PixelOffsets
465 {
466 public:
467         virtual void operator() (const IVec2& pixCoord, IVec2 (&dst)[4]) const = 0;
468         virtual ~PixelOffsets (void) {}
469 };
470
471 class MultiplePixelOffsets : public PixelOffsets
472 {
473 public:
474         MultiplePixelOffsets (const IVec2& a,
475                                                   const IVec2& b,
476                                                   const IVec2& c,
477                                                   const IVec2& d)
478         {
479                 m_offsets[0] = a;
480                 m_offsets[1] = b;
481                 m_offsets[2] = c;
482                 m_offsets[3] = d;
483         }
484
485         void operator() (const IVec2& /* pixCoord */, IVec2 (&dst)[4]) const
486         {
487                 for (int i = 0; i < DE_LENGTH_OF_ARRAY(dst); i++)
488                         dst[i] = m_offsets[i];
489         }
490
491 private:
492         IVec2 m_offsets[4];
493 };
494
495 class SinglePixelOffsets : public MultiplePixelOffsets
496 {
497 public:
498         SinglePixelOffsets (const IVec2& offset)
499                 : MultiplePixelOffsets(offset + IVec2(0, 1),
500                                                            offset + IVec2(1, 1),
501                                                            offset + IVec2(1, 0),
502                                                            offset + IVec2(0, 0))
503         {
504         }
505 };
506
507 class DynamicSinglePixelOffsets : public PixelOffsets
508 {
509 public:
510         DynamicSinglePixelOffsets (const IVec2& offsetRange) : m_offsetRange(offsetRange) {}
511
512         void operator() (const IVec2& pixCoord, IVec2 (&dst)[4]) const
513         {
514                 const int offsetRangeSize = m_offsetRange.y() - m_offsetRange.x() + 1;
515                 SinglePixelOffsets(tcu::mod(pixCoord.swizzle(1,0), IVec2(offsetRangeSize)) + m_offsetRange.x())(IVec2(), dst);
516         }
517
518 private:
519         IVec2 m_offsetRange;
520 };
521
522 template <typename T>
523 static inline T triQuadInterpolate (const T (&values)[4], float xFactor, float yFactor)
524 {
525         if (xFactor + yFactor < 1.0f)
526                 return values[0] + (values[2]-values[0])*xFactor                + (values[1]-values[0])*yFactor;
527         else
528                 return values[3] + (values[1]-values[3])*(1.0f-xFactor) + (values[2]-values[3])*(1.0f-yFactor);
529 }
530
531 template <int N>
532 static inline void computeTexCoordVecs (const vector<float>& texCoords, tcu::Vector<float, N> (&dst)[4])
533 {
534         DE_ASSERT((int)texCoords.size() == 4*N);
535         for (int i = 0; i < 4; i++)
536         for (int j = 0; j < N; j++)
537                 dst[i][j] = texCoords[i*N + j];
538 }
539
540 #if defined(DE_DEBUG)
541 // Whether offsets correspond to the sample offsets used with plain textureGather().
542 static inline bool isZeroOffsetOffsets (const IVec2 (&offsets)[4])
543 {
544         IVec2 ref[4];
545         SinglePixelOffsets(IVec2(0))(IVec2(), ref);
546         return std::equal(DE_ARRAY_BEGIN(offsets),
547                                           DE_ARRAY_END(offsets),
548                                           DE_ARRAY_BEGIN(ref));
549 }
550 #endif
551
552 template <typename ColorScalarType>
553 static tcu::Vector<ColorScalarType, 4> gatherOffsets (const tcu::Texture2DView& texture, const tcu::Sampler& sampler, const Vec2& coord, int componentNdx, const IVec2 (&offsets)[4])
554 {
555         return texture.gatherOffsets(sampler, coord.x(), coord.y(), componentNdx, offsets).cast<ColorScalarType>();
556 }
557
558 template <typename ColorScalarType>
559 static tcu::Vector<ColorScalarType, 4> gatherOffsets (const tcu::Texture2DArrayView& texture, const tcu::Sampler& sampler, const Vec3& coord, int componentNdx, const IVec2 (&offsets)[4])
560 {
561         return texture.gatherOffsets(sampler, coord.x(), coord.y(), coord.z(), componentNdx, offsets).cast<ColorScalarType>();
562 }
563
564 template <typename ColorScalarType>
565 static tcu::Vector<ColorScalarType, 4> gatherOffsets (const tcu::TextureCubeView& texture, const tcu::Sampler& sampler, const Vec3& coord, int componentNdx, const IVec2 (&offsets)[4])
566 {
567         DE_ASSERT(isZeroOffsetOffsets(offsets));
568         DE_UNREF(offsets);
569         return texture.gather(sampler, coord.x(), coord.y(), coord.z(), componentNdx).cast<ColorScalarType>();
570 }
571
572 static Vec4 gatherOffsetsCompare (const tcu::Texture2DView& texture, const tcu::Sampler& sampler, float refZ, const Vec2& coord, const IVec2 (&offsets)[4])
573 {
574         return texture.gatherOffsetsCompare(sampler, refZ, coord.x(), coord.y(), offsets);
575 }
576
577 static Vec4 gatherOffsetsCompare (const tcu::Texture2DArrayView& texture, const tcu::Sampler& sampler, float refZ, const Vec3& coord, const IVec2 (&offsets)[4])
578 {
579         return texture.gatherOffsetsCompare(sampler, refZ, coord.x(), coord.y(), coord.z(), offsets);
580 }
581
582 static Vec4 gatherOffsetsCompare (const tcu::TextureCubeView& texture, const tcu::Sampler& sampler, float refZ, const Vec3& coord, const IVec2 (&offsets)[4])
583 {
584         DE_ASSERT(isZeroOffsetOffsets(offsets));
585         DE_UNREF(offsets);
586         return texture.gatherCompare(sampler, refZ, coord.x(), coord.y(), coord.z());
587 }
588
589 template <typename PrecType, typename ColorScalarT>
590 static bool isGatherOffsetsResultValid (const tcu::TextureCubeView&                             texture,
591                                                                                 const tcu::Sampler&                                             sampler,
592                                                                                 const PrecType&                                                 prec,
593                                                                                 const Vec3&                                                             coord,
594                                                                                 int                                                                             componentNdx,
595                                                                                 const IVec2                                                             (&offsets)[4],
596                                                                                 const tcu::Vector<ColorScalarT, 4>&             result)
597 {
598         DE_ASSERT(isZeroOffsetOffsets(offsets));
599         DE_UNREF(offsets);
600         return tcu::isGatherResultValid(texture, sampler, prec, coord, componentNdx, result);
601 }
602
603 static bool isGatherOffsetsCompareResultValid (const tcu::TextureCubeView&              texture,
604                                                                                            const tcu::Sampler&                          sampler,
605                                                                                            const tcu::TexComparePrecision&      prec,
606                                                                                            const Vec3&                                          coord,
607                                                                                            const IVec2                                          (&offsets)[4],
608                                                                                            float                                                        cmpReference,
609                                                                                            const Vec4&                                          result)
610 {
611         DE_ASSERT(isZeroOffsetOffsets(offsets));
612         DE_UNREF(offsets);
613         return tcu::isGatherCompareResultValid(texture, sampler, prec, coord, cmpReference, result);
614 }
615
616 template <typename ColorScalarType, typename PrecType, typename TexViewT, typename TexCoordT>
617 static bool verifyGatherOffsets (TestLog&                                               log,
618                                                                  const ConstPixelBufferAccess&  result,
619                                                                  const TexViewT&                                texture,
620                                                                  const TexCoordT                                (&texCoords)[4],
621                                                                  const tcu::Sampler&                    sampler,
622                                                                  const PrecType&                                lookupPrec,
623                                                                  int                                                    componentNdx,
624                                                                  const PixelOffsets&                    getPixelOffsets)
625 {
626         typedef tcu::Vector<ColorScalarType, 4> ColorVec;
627
628         const int                                       width                   = result.getWidth();
629         const int                                       height                  = result.getWidth();
630         tcu::TextureLevel                       ideal                   (result.getFormat(), width, height);
631         const PixelBufferAccess         idealAccess             = ideal.getAccess();
632         tcu::Surface                            errorMask               (width, height);
633         bool                                            success                 = true;
634
635         tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec());
636
637         for (int py = 0; py < height; py++)
638         for (int px = 0; px < width; px++)
639         {
640                 IVec2           offsets[4];
641                 getPixelOffsets(IVec2(px, py), offsets);
642
643                 const Vec2                      viewportCoord   = (Vec2((float)px, (float)py) + 0.5f) / Vec2((float)width, (float)height);
644                 const TexCoordT         texCoord                = triQuadInterpolate(texCoords, viewportCoord.x(), viewportCoord.y());
645                 const ColorVec          resultPix               = result.getPixelT<ColorScalarType>(px, py);
646                 const ColorVec          idealPix                = gatherOffsets<ColorScalarType>(texture, sampler, texCoord, componentNdx, offsets);
647
648                 idealAccess.setPixel(idealPix, px, py);
649
650                 if (tcu::boolAny(tcu::logicalAnd(lookupPrec.colorMask,
651                                                                                  tcu::greaterThan(tcu::absDiff(resultPix, idealPix),
652                                                                                                                   lookupPrec.colorThreshold.template cast<ColorScalarType>()))))
653                 {
654                         if (!isGatherOffsetsResultValid(texture, sampler, lookupPrec, texCoord, componentNdx, offsets, resultPix))
655                         {
656                                 errorMask.setPixel(px, py, tcu::RGBA::red());
657                                 success = false;
658                         }
659                 }
660         }
661
662         log << TestLog::ImageSet("VerifyResult", "Verification result")
663                 << TestLog::Image("Rendered", "Rendered image", result);
664
665         if (!success)
666         {
667                 log << TestLog::Image("Reference", "Ideal reference image", ideal)
668                         << TestLog::Image("ErrorMask", "Error mask", errorMask);
669         }
670
671         log << TestLog::EndImageSet;
672
673         return success;
674 }
675
676 class PixelCompareRefZ
677 {
678 public:
679         virtual float operator() (const IVec2& pixCoord) const = 0;
680 };
681
682 class PixelCompareRefZDefault : public PixelCompareRefZ
683 {
684 public:
685         PixelCompareRefZDefault (const IVec2& renderSize) : m_renderSize(renderSize) {}
686
687         float operator() (const IVec2& pixCoord) const
688         {
689                 return ((float)pixCoord.x() + 0.5f) / (float)m_renderSize.x();
690         }
691
692 private:
693         IVec2 m_renderSize;
694 };
695
696 template <typename TexViewT, typename TexCoordT>
697 static bool verifyGatherOffsetsCompare (TestLog&                                                        log,
698                                                                                 const ConstPixelBufferAccess&           result,
699                                                                                 const TexViewT&                                         texture,
700                                                                                 const TexCoordT                                         (&texCoords)[4],
701                                                                                 const tcu::Sampler&                                     sampler,
702                                                                                 const tcu::TexComparePrecision&         compPrec,
703                                                                                 const PixelCompareRefZ&                         getPixelRefZ,
704                                                                                 const PixelOffsets&                                     getPixelOffsets)
705 {
706         const int                                       width                   = result.getWidth();
707         const int                                       height                  = result.getWidth();
708         tcu::Surface                            ideal                   (width, height);
709         const PixelBufferAccess         idealAccess             = ideal.getAccess();
710         tcu::Surface                            errorMask               (width, height);
711         bool                                            success                 = true;
712
713         tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec());
714
715         for (int py = 0; py < height; py++)
716         for (int px = 0; px < width; px++)
717         {
718                 IVec2           offsets[4];
719                 getPixelOffsets(IVec2(px, py), offsets);
720
721                 const Vec2                      viewportCoord   = (Vec2((float)px, (float)py) + 0.5f) / Vec2((float)width, (float)height);
722                 const TexCoordT         texCoord                = triQuadInterpolate(texCoords, viewportCoord.x(), viewportCoord.y());
723                 const float                     refZ                    = getPixelRefZ(IVec2(px, py));
724                 const Vec4                      resultPix               = result.getPixel(px, py);
725                 const Vec4                      idealPix                = gatherOffsetsCompare(texture, sampler, refZ, texCoord, offsets);
726
727                 idealAccess.setPixel(idealPix, px, py);
728
729                 if (!tcu::boolAll(tcu::equal(resultPix, idealPix)))
730                 {
731                         if (!isGatherOffsetsCompareResultValid(texture, sampler, compPrec, texCoord, offsets, refZ, resultPix))
732                         {
733                                 errorMask.setPixel(px, py, tcu::RGBA::red());
734                                 success = false;
735                         }
736                 }
737         }
738
739         log << TestLog::ImageSet("VerifyResult", "Verification result")
740                 << TestLog::Image("Rendered", "Rendered image", result);
741
742         if (!success)
743         {
744                 log << TestLog::Image("Reference", "Ideal reference image", ideal)
745                         << TestLog::Image("ErrorMask", "Error mask", errorMask);
746         }
747
748         log << TestLog::EndImageSet;
749
750         return success;
751 }
752
753 enum GatherType
754 {
755         GATHERTYPE_BASIC = 0,
756         GATHERTYPE_OFFSET,
757         GATHERTYPE_OFFSET_DYNAMIC,
758         GATHERTYPE_OFFSETS,
759
760         GATHERTYPE_LAST
761 };
762
763 enum GatherCaseFlags
764 {
765         GATHERCASE_DONT_SAMPLE_CUBE_CORNERS     = (1<<0)        //!< For cube map cases: do not sample cube corners
766 };
767
768 enum OffsetSize
769 {
770         OFFSETSIZE_NONE = 0,
771         OFFSETSIZE_MINIMUM_REQUIRED,
772         OFFSETSIZE_IMPLEMENTATION_MAXIMUM,
773
774         OFFSETSIZE_LAST
775 };
776
777 static inline const char* gatherTypeName (GatherType type)
778 {
779         switch (type)
780         {
781                 case GATHERTYPE_BASIC:                          return "basic";
782                 case GATHERTYPE_OFFSET:                         return "offset";
783                 case GATHERTYPE_OFFSET_DYNAMIC:         return "offset_dynamic";
784                 case GATHERTYPE_OFFSETS:                        return "offsets";
785                 default: DE_ASSERT(false); return DE_NULL;
786         }
787 }
788
789 static inline const char* gatherTypeDescription (GatherType type)
790 {
791         switch (type)
792         {
793                 case GATHERTYPE_BASIC:                          return "textureGather";
794                 case GATHERTYPE_OFFSET:                         return "textureGatherOffset";
795                 case GATHERTYPE_OFFSET_DYNAMIC:         return "textureGatherOffset with dynamic offsets";
796                 case GATHERTYPE_OFFSETS:                        return "textureGatherOffsets";
797                 default: DE_ASSERT(false); return DE_NULL;
798         }
799 }
800
801 static inline bool requireGpuShader5 (GatherType gatherType, OffsetSize offsetSize)
802 {
803         return gatherType == GATHERTYPE_OFFSET_DYNAMIC || gatherType == GATHERTYPE_OFFSETS
804                 || offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM; // \note Implementation limits are not available while generating the shaders, they are passed dynamically at runtime
805 }
806
807 struct GatherArgs
808 {
809         int             componentNdx;   // If negative, implicit component index 0 is used (i.e. the parameter is not given).
810         IVec2   offsets[4];             // \note Unless GATHERTYPE_OFFSETS is used, only offsets[0] is relevant; also, for GATHERTYPE_OFFSET_DYNAMIC, none are relevant.
811
812         GatherArgs (void)
813                 : componentNdx(-1)
814         {
815                 std::fill(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), IVec2());
816         }
817
818         GatherArgs (int comp,
819                                 const IVec2& off0 = IVec2(),
820                                 const IVec2& off1 = IVec2(),
821                                 const IVec2& off2 = IVec2(),
822                                 const IVec2& off3 = IVec2())
823                 : componentNdx(comp)
824         {
825                 offsets[0] = off0;
826                 offsets[1] = off1;
827                 offsets[2] = off2;
828                 offsets[3] = off3;
829         }
830 };
831
832 static MovePtr<PixelOffsets> makePixelOffsetsFunctor (GatherType gatherType, const GatherArgs& gatherArgs, const IVec2& offsetRange)
833 {
834         if (gatherType == GATHERTYPE_BASIC || gatherType == GATHERTYPE_OFFSET)
835         {
836                 const IVec2 offset = gatherType == GATHERTYPE_BASIC ? IVec2(0) : gatherArgs.offsets[0];
837                 return MovePtr<PixelOffsets>(new SinglePixelOffsets(offset));
838         }
839         else if (gatherType == GATHERTYPE_OFFSET_DYNAMIC)
840         {
841                 return MovePtr<PixelOffsets>(new DynamicSinglePixelOffsets(offsetRange));
842         }
843         else if (gatherType == GATHERTYPE_OFFSETS)
844                 return MovePtr<PixelOffsets>(new MultiplePixelOffsets(gatherArgs.offsets[0],
845                                                                                                                           gatherArgs.offsets[1],
846                                                                                                                           gatherArgs.offsets[2],
847                                                                                                                           gatherArgs.offsets[3]));
848         else
849         {
850                 DE_ASSERT(false);
851                 return MovePtr<PixelOffsets>(DE_NULL);
852         }
853 }
854
855 static inline glu::DataType getSamplerType (TextureType textureType, const tcu::TextureFormat& format)
856 {
857         if (isDepthFormat(format))
858         {
859                 switch (textureType)
860                 {
861                         case TEXTURETYPE_2D:            return glu::TYPE_SAMPLER_2D_SHADOW;
862                         case TEXTURETYPE_2D_ARRAY:      return glu::TYPE_SAMPLER_2D_ARRAY_SHADOW;
863                         case TEXTURETYPE_CUBE:          return glu::TYPE_SAMPLER_CUBE_SHADOW;
864                         default: DE_ASSERT(false); return glu::TYPE_LAST;
865                 }
866         }
867         else
868         {
869                 switch (textureType)
870                 {
871                         case TEXTURETYPE_2D:            return glu::getSampler2DType(format);
872                         case TEXTURETYPE_2D_ARRAY:      return glu::getSampler2DArrayType(format);
873                         case TEXTURETYPE_CUBE:          return glu::getSamplerCubeType(format);
874                         default: DE_ASSERT(false); return glu::TYPE_LAST;
875                 }
876         }
877 }
878
879 static inline glu::DataType getSamplerGatherResultType (glu::DataType samplerType)
880 {
881         switch (samplerType)
882         {
883                 case glu::TYPE_SAMPLER_2D_SHADOW:
884                 case glu::TYPE_SAMPLER_2D_ARRAY_SHADOW:
885                 case glu::TYPE_SAMPLER_CUBE_SHADOW:
886                 case glu::TYPE_SAMPLER_2D:
887                 case glu::TYPE_SAMPLER_2D_ARRAY:
888                 case glu::TYPE_SAMPLER_CUBE:
889                         return glu::TYPE_FLOAT_VEC4;
890
891                 case glu::TYPE_INT_SAMPLER_2D:
892                 case glu::TYPE_INT_SAMPLER_2D_ARRAY:
893                 case glu::TYPE_INT_SAMPLER_CUBE:
894                         return glu::TYPE_INT_VEC4;
895
896                 case glu::TYPE_UINT_SAMPLER_2D:
897                 case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
898                 case glu::TYPE_UINT_SAMPLER_CUBE:
899                         return glu::TYPE_UINT_VEC4;
900
901                 default:
902                         DE_ASSERT(false);
903                         return glu::TYPE_LAST;
904         }
905 }
906
907 static inline int getNumTextureSamplingDimensions (TextureType type)
908 {
909         switch (type)
910         {
911                 case TEXTURETYPE_2D:            return 2;
912                 case TEXTURETYPE_2D_ARRAY:      return 3;
913                 case TEXTURETYPE_CUBE:          return 3;
914                 default: DE_ASSERT(false); return -1;
915         }
916 }
917
918 vector<GatherArgs> generateBasic2DCaseIterations (GatherType gatherType, const tcu::TextureFormat& textureFormat, const IVec2& offsetRange)
919 {
920         const int                       numComponentCases       = isDepthFormat(textureFormat) ? 1 : 4+1; // \note For non-depth textures, test explicit components 0 to 3 and implicit component 0.
921         vector<GatherArgs>      result;
922
923         for (int componentCaseNdx = 0; componentCaseNdx < numComponentCases; componentCaseNdx++)
924         {
925                 const int componentNdx = componentCaseNdx - 1;
926
927                 switch (gatherType)
928                 {
929                         case GATHERTYPE_BASIC:
930                                 result.push_back(GatherArgs(componentNdx));
931                                 break;
932
933                         case GATHERTYPE_OFFSET:
934                         {
935                                 const int min   = offsetRange.x();
936                                 const int max   = offsetRange.y();
937                                 const int hmin  = divRoundToZero(min, 2);
938                                 const int hmax  = divRoundToZero(max, 2);
939
940                                 result.push_back(GatherArgs(componentNdx, IVec2(min, max)));
941
942                                 if (componentCaseNdx == 0) // Don't test all offsets variants for all color components (they should be pretty orthogonal).
943                                 {
944                                         result.push_back(GatherArgs(componentNdx, IVec2(min,    min)));
945                                         result.push_back(GatherArgs(componentNdx, IVec2(max,    min)));
946                                         result.push_back(GatherArgs(componentNdx, IVec2(max,    max)));
947
948                                         result.push_back(GatherArgs(componentNdx, IVec2(0,              hmax)));
949                                         result.push_back(GatherArgs(componentNdx, IVec2(hmin,   0)));
950                                         result.push_back(GatherArgs(componentNdx, IVec2(0,              0)));
951                                 }
952
953                                 break;
954                         }
955
956                         case GATHERTYPE_OFFSET_DYNAMIC:
957                                 result.push_back(GatherArgs(componentNdx));
958                                 break;
959
960                         case GATHERTYPE_OFFSETS:
961                         {
962                                 const int min   = offsetRange.x();
963                                 const int max   = offsetRange.y();
964                                 const int hmin  = divRoundToZero(min, 2);
965                                 const int hmax  = divRoundToZero(max, 2);
966
967                                 result.push_back(GatherArgs(componentNdx,
968                                                                                         IVec2(min,      min),
969                                                                                         IVec2(min,      max),
970                                                                                         IVec2(max,      min),
971                                                                                         IVec2(max,      max)));
972
973                                 if (componentCaseNdx == 0) // Don't test all offsets variants for all color components (they should be pretty orthogonal).
974                                         result.push_back(GatherArgs(componentNdx,
975                                                                                                 IVec2(min,      hmax),
976                                                                                                 IVec2(hmin,     max),
977                                                                                                 IVec2(0,        hmax),
978                                                                                                 IVec2(hmax,     0)));
979                                 break;
980                         }
981
982                         default:
983                                 DE_ASSERT(false);
984                 }
985         }
986
987         return result;
988 }
989
990 struct GatherCaseBaseParams
991 {
992         GatherType                                      gatherType;
993         OffsetSize                                      offsetSize;
994         tcu::TextureFormat                      textureFormat;
995         tcu::Sampler::CompareMode       shadowCompareMode;
996         tcu::Sampler::WrapMode          wrapS;
997         tcu::Sampler::WrapMode          wrapT;
998         MaybeTextureSwizzle                     textureSwizzle;
999         tcu::Sampler::FilterMode        minFilter;
1000         tcu::Sampler::FilterMode        magFilter;
1001         int                                                     baseLevel;
1002         deUint32                                        flags;
1003         TextureType                                     textureType;
1004         ImageBackingMode                        sparseCase;
1005
1006         GatherCaseBaseParams (const TextureType                                 textureType_,
1007                                                   const GatherType                                      gatherType_,
1008                                                   const OffsetSize                                      offsetSize_,
1009                                                   const tcu::TextureFormat                      textureFormat_,
1010                                                   const tcu::Sampler::CompareMode       shadowCompareMode_,
1011                                                   const tcu::Sampler::WrapMode          wrapS_,
1012                                                   const tcu::Sampler::WrapMode          wrapT_,
1013                                                   const MaybeTextureSwizzle&            textureSwizzle_,
1014                                                   const tcu::Sampler::FilterMode        minFilter_,
1015                                                   const tcu::Sampler::FilterMode        magFilter_,
1016                                                   const int                                                     baseLevel_,
1017                                                   const deUint32                                        flags_,
1018                                                   const ImageBackingMode                        sparseCase_)
1019                 : gatherType                    (gatherType_)
1020                 , offsetSize                    (offsetSize_)
1021                 , textureFormat                 (textureFormat_)
1022                 , shadowCompareMode             (shadowCompareMode_)
1023                 , wrapS                                 (wrapS_)
1024                 , wrapT                                 (wrapT_)
1025                 , textureSwizzle                (textureSwizzle_)
1026                 , minFilter                             (minFilter_)
1027                 , magFilter                             (magFilter_)
1028                 , baseLevel                             (baseLevel_)
1029                 , flags                                 (flags_)
1030                 , textureType                   (textureType_)
1031                 , sparseCase                    (sparseCase_)
1032         {}
1033
1034         GatherCaseBaseParams (void)
1035                 : gatherType                    (GATHERTYPE_LAST)
1036                 , offsetSize                    (OFFSETSIZE_LAST)
1037                 , textureFormat                 ()
1038                 , shadowCompareMode             (tcu::Sampler::COMPAREMODE_LAST)
1039                 , wrapS                                 (tcu::Sampler::WRAPMODE_LAST)
1040                 , wrapT                                 (tcu::Sampler::WRAPMODE_LAST)
1041                 , textureSwizzle                (MaybeTextureSwizzle::createNoneTextureSwizzle())
1042                 , minFilter                             (tcu::Sampler::FILTERMODE_LAST)
1043                 , magFilter                             (tcu::Sampler::FILTERMODE_LAST)
1044                 , baseLevel                             (0)
1045                 , flags                                 (0)
1046                 , textureType                   (TEXTURETYPE_LAST)
1047                 , sparseCase                    (ShaderRenderCaseInstance::IMAGE_BACKING_MODE_REGULAR)
1048         {}
1049 };
1050
1051 IVec2 getOffsetRange (const OffsetSize offsetSize, const vk::VkPhysicalDeviceLimits& deviceLimits)
1052 {
1053         switch (offsetSize)
1054         {
1055                 case OFFSETSIZE_NONE:
1056                         return IVec2(0);
1057
1058                 case OFFSETSIZE_MINIMUM_REQUIRED:
1059                         // \note Defined by spec.
1060                         return IVec2(SPEC_MAX_MIN_OFFSET,
1061                                                  SPEC_MIN_MAX_OFFSET);
1062
1063                 case OFFSETSIZE_IMPLEMENTATION_MAXIMUM:
1064                         return IVec2(deviceLimits.minTexelGatherOffset, deviceLimits.maxTexelGatherOffset);
1065
1066                 default:
1067                         DE_ASSERT(false);
1068                         return IVec2(-1);
1069         }
1070 }
1071
1072 IVec2 getOffsetRange (const OffsetSize offsetSize)
1073 {
1074         switch (offsetSize)
1075         {
1076                 case OFFSETSIZE_NONE:
1077                         return IVec2(0);
1078
1079                 case OFFSETSIZE_MINIMUM_REQUIRED:
1080                         // \note Defined by spec.
1081                         return IVec2(SPEC_MAX_MIN_OFFSET,
1082                                                  SPEC_MIN_MAX_OFFSET);
1083
1084                 case OFFSETSIZE_IMPLEMENTATION_MAXIMUM:
1085                         DE_FATAL("Not known");
1086                         return IVec2(-1);
1087
1088                 default:
1089                         DE_ASSERT(false);
1090                         return IVec2(-1);
1091         }
1092 }
1093
1094 class TextureGatherInstance : public ShaderRenderCaseInstance
1095 {
1096 public:
1097                                                                                 TextureGatherInstance           (Context&                                               context,
1098                                                                                                                                          const GatherCaseBaseParams&    baseParams);
1099         virtual                                                         ~TextureGatherInstance          (void);
1100
1101         virtual tcu::TestStatus                         iterate                                         (void);
1102
1103 protected:
1104         void                                                            init                                            (void);
1105
1106         virtual int                                                     getNumIterations                        (void) const = 0;
1107         virtual GatherArgs                                      getGatherArgs                           (int iterationNdx) const = 0;
1108
1109         virtual void                                            setupDefaultInputs                      (void);
1110         virtual void                                            setupUniforms                           (const tcu::Vec4&);
1111
1112         template <typename TexViewT, typename TexCoordT>
1113         bool                                                            verify                                          (const ConstPixelBufferAccess&          rendered,
1114                                                                                                                                          const TexViewT&                                        texture,
1115                                                                                                                                          const TexCoordT                                        (&bottomLeft)[4],
1116                                                                                                                                          const GatherArgs&                                      gatherArgs) const;
1117
1118         virtual TextureBindingSp                        createTexture                           (void) = 0;
1119         virtual vector<float>                           computeQuadTexCoord                     (int iterationNdx) const = 0;
1120         virtual bool                                            verify                                          (int iterationNdx, const ConstPixelBufferAccess& rendered) const = 0;
1121
1122 protected:
1123         static const IVec2                                      RENDER_SIZE;
1124
1125         const GatherCaseBaseParams                      m_baseParams;
1126
1127 private:
1128         const tcu::TextureFormat                        m_colorBufferFormat;
1129         int                                                                     m_currentIteration;
1130 };
1131
1132 const IVec2 TextureGatherInstance::RENDER_SIZE = IVec2(64, 64);
1133
1134 TextureGatherInstance::TextureGatherInstance (Context&                                          context,
1135                                                                                           const GatherCaseBaseParams&   baseParams)
1136         : ShaderRenderCaseInstance      (context, false, DE_NULL, DE_NULL, DE_NULL, baseParams.sparseCase)
1137         , m_baseParams                          (baseParams)
1138         , m_colorBufferFormat           (tcu::TextureFormat(tcu::TextureFormat::RGBA,
1139                                                                                                         isDepthFormat(baseParams.textureFormat) ? tcu::TextureFormat::UNORM_INT8 : baseParams.textureFormat.type))
1140         , m_currentIteration            (0)
1141 {
1142         DE_ASSERT((m_baseParams.gatherType == GATHERTYPE_BASIC) == (m_baseParams.offsetSize == OFFSETSIZE_NONE));
1143         DE_ASSERT((m_baseParams.shadowCompareMode != tcu::Sampler::COMPAREMODE_NONE) == isDepthFormat(m_baseParams.textureFormat));
1144         DE_ASSERT(isUnormFormatType(m_colorBufferFormat.type)                                           ||
1145                           m_colorBufferFormat.type == tcu::TextureFormat::UNSIGNED_INT8         ||
1146                           m_colorBufferFormat.type == tcu::TextureFormat::UNSIGNED_INT16        ||
1147                           m_colorBufferFormat.type == tcu::TextureFormat::SIGNED_INT8           ||
1148                           m_colorBufferFormat.type == tcu::TextureFormat::SIGNED_INT16);
1149         DE_ASSERT(glu::isGLInternalColorFormatFilterable(glu::getInternalFormat(m_colorBufferFormat)) ||
1150                           (m_baseParams.magFilter == tcu::Sampler::NEAREST && (m_baseParams.minFilter == tcu::Sampler::NEAREST || m_baseParams.minFilter == tcu::Sampler::NEAREST_MIPMAP_NEAREST)));
1151         DE_ASSERT(m_baseParams.textureType == TEXTURETYPE_CUBE || !(m_baseParams.flags & GATHERCASE_DONT_SAMPLE_CUBE_CORNERS));
1152
1153         m_renderSize                            = RENDER_SIZE.asUint();
1154         m_colorFormat                           = vk::mapTextureFormat(m_colorBufferFormat);
1155 }
1156
1157 TextureGatherInstance::~TextureGatherInstance (void)
1158 {
1159 }
1160
1161 void TextureGatherInstance::init (void)
1162 {
1163         TestLog&                                                log                                     = m_context.getTestContext().getLog();
1164         TextureBindingSp                                textureBinding;
1165         TextureBinding::Parameters              textureParams;
1166
1167         // Check prerequisites.
1168         if (requireGpuShader5(m_baseParams.gatherType, m_baseParams.offsetSize))
1169         {
1170                 const vk::VkPhysicalDeviceFeatures&             deviceFeatures  = m_context.getDeviceFeatures();
1171                 if (!deviceFeatures.shaderImageGatherExtended)
1172                         TCU_THROW(NotSupportedError, "Extended set of image gather instructions are not supported");
1173         }
1174
1175         // Log and check implementation offset limits, if appropriate.
1176         if (m_baseParams.offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
1177         {
1178                 const IVec2             offsetRange             = getOffsetRange(m_baseParams.offsetSize, m_context.getDeviceProperties().limits);
1179                 log << TestLog::Integer("ImplementationMinTextureGatherOffset", "Implementation's value for minTexelGatherOffset", "", QP_KEY_TAG_NONE, offsetRange[0])
1180                         << TestLog::Integer("ImplementationMaxTextureGatherOffset", "Implementation's value for maxTexelGatherOffset", "", QP_KEY_TAG_NONE, offsetRange[1]);
1181                 TCU_CHECK_MSG(offsetRange[0] <= SPEC_MAX_MIN_OFFSET, ("minTexelGatherOffset must be at most " + de::toString((int)SPEC_MAX_MIN_OFFSET)).c_str());
1182                 TCU_CHECK_MSG(offsetRange[1] >= SPEC_MIN_MAX_OFFSET, ("maxTexelGatherOffset must be at least " + de::toString((int)SPEC_MIN_MAX_OFFSET)).c_str());
1183         }
1184
1185         // Initialize texture.
1186
1187         textureBinding = createTexture();
1188
1189         if (m_baseParams.textureSwizzle.isSome())
1190         {
1191                 const tcu::Vector<TextureSwizzleComponent, 4>&  swizzle         = m_baseParams.textureSwizzle.getSwizzle();
1192
1193                 const vk::VkComponentMapping                                    components      =
1194                 {
1195                         getTextureSwizzleComponent(swizzle[0]),
1196                         getTextureSwizzleComponent(swizzle[1]),
1197                         getTextureSwizzleComponent(swizzle[2]),
1198                         getTextureSwizzleComponent(swizzle[3])
1199                 };
1200
1201                 textureParams.componentMapping = components;
1202         }
1203
1204         if (m_baseParams.baseLevel != 0)
1205                 textureParams.baseMipLevel = m_baseParams.baseLevel;
1206
1207         textureBinding->setParameters(textureParams);
1208         m_textures.push_back(textureBinding);
1209
1210         log << TestLog::Message << "Texture base level is " << m_baseParams.baseLevel << TestLog::EndMessage
1211                 << TestLog::Message << "s and t wrap modes are "
1212                                                         << vk::mapWrapMode(m_baseParams.wrapS) << " and "
1213                                                         << vk::mapWrapMode(m_baseParams.wrapT) << ", respectively" << TestLog::EndMessage
1214                 << TestLog::Message << "Minification and magnification filter modes are "
1215                                                         << vk::mapFilterMode(m_baseParams.minFilter) << " and "
1216                                                         << vk::mapFilterMode(m_baseParams.magFilter) << ", respectively "
1217                                                         << "(note that they should have no effect on gather result)"
1218                                                         << TestLog::EndMessage
1219                 << TestLog::Message << "Using texture swizzle " << m_baseParams.textureSwizzle << TestLog::EndMessage;
1220
1221         if (m_baseParams.shadowCompareMode != tcu::Sampler::COMPAREMODE_NONE)
1222                 log << TestLog::Message << "Using texture compare func " << vk::mapCompareMode(m_baseParams.shadowCompareMode) << TestLog::EndMessage;
1223 }
1224
1225 void TextureGatherInstance::setupDefaultInputs (void)
1226 {
1227         const int                               numVertices                                             = 4;
1228         const float                             position[4*2]                                   =
1229         {
1230                 -1.0f, -1.0f,
1231                 -1.0f, +1.0f,
1232                 +1.0f, -1.0f,
1233                 +1.0f, +1.0f,
1234         };
1235         const float                             normalizedCoord[4*2]                    =
1236         {
1237                 0.0f, 0.0f,
1238                 0.0f, 1.0f,
1239                 1.0f, 0.0f,
1240                 1.0f, 1.0f,
1241         };
1242         const vector<float>             texCoord                                                = computeQuadTexCoord(m_currentIteration);
1243         const bool                              needNormalizedCoordInShader             = m_baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC || isDepthFormat(m_baseParams.textureFormat);
1244
1245         addAttribute(0u, vk::VK_FORMAT_R32G32_SFLOAT, 2 * (deUint32)sizeof(float), numVertices, position);
1246
1247         if (texCoord.size() == 2*4)
1248                 addAttribute(1u, vk::VK_FORMAT_R32G32_SFLOAT, 2 * (deUint32)sizeof(float), numVertices, texCoord.data());
1249         else if (texCoord.size() == 3*4)
1250                 addAttribute(1u, vk::VK_FORMAT_R32G32B32_SFLOAT, 3 * (deUint32)sizeof(float), numVertices, texCoord.data());
1251         else
1252                 DE_ASSERT(false);
1253
1254         if (needNormalizedCoordInShader)
1255                 addAttribute(2u, vk::VK_FORMAT_R32G32_SFLOAT, 2 * (deUint32)sizeof(float), numVertices, normalizedCoord);
1256 }
1257
1258 tcu::TestStatus TextureGatherInstance::iterate (void)
1259 {
1260         TestLog&                                                log                                             = m_context.getTestContext().getLog();
1261         const tcu::ScopedLogSection             iterationSection                (log, "Iteration" + de::toString(m_currentIteration), "Iteration " + de::toString(m_currentIteration));
1262
1263         // Render.
1264
1265         {
1266                 const deUint32                          numVertices             = 4;
1267                 const deUint32                          numTriangles    = 2;
1268                 const deUint16                          indices[6]              = { 0, 1, 2, 2, 1, 3 };
1269                 const vector<float>                     texCoord                = computeQuadTexCoord(m_currentIteration);
1270
1271                 if (texCoord.size() == 2*4)
1272                 {
1273                         Vec2 texCoordVec[4];
1274                         computeTexCoordVecs(texCoord, texCoordVec);
1275                         log << TestLog::Message << "Texture coordinates run from " << texCoordVec[0] << " to " << texCoordVec[3] << TestLog::EndMessage;
1276                 }
1277                 else if (texCoord.size() == 3*4)
1278                 {
1279                         Vec3 texCoordVec[4];
1280                         computeTexCoordVecs(texCoord, texCoordVec);
1281                         log << TestLog::Message << "Texture coordinates run from " << texCoordVec[0] << " to " << texCoordVec[3] << TestLog::EndMessage;
1282                 }
1283                 else
1284                         DE_ASSERT(false);
1285
1286                 m_vertexShaderName              = "vert";
1287                 m_fragmentShaderName    = "frag_" + de::toString(m_currentIteration);
1288
1289                 setup();
1290
1291                 render(numVertices, numTriangles, indices);
1292         }
1293
1294         // Verify result.
1295
1296         if (!verify(m_currentIteration, getResultImage().getAccess()))
1297                 return tcu::TestStatus::fail("Result verification failed");
1298
1299         m_currentIteration++;
1300         if (m_currentIteration == getNumIterations())
1301                 return tcu::TestStatus::pass("Pass");
1302         else
1303                 return tcu::TestStatus::incomplete();
1304 }
1305
1306 void TextureGatherInstance::setupUniforms (const tcu::Vec4&)
1307 {
1308         deUint32        binding         = 0;
1309
1310         useSampler(binding++, 0u);
1311
1312         if (m_baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC)
1313                 addUniform(binding++, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::Vec2), RENDER_SIZE.asFloat().getPtr());
1314
1315         if (m_baseParams.offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
1316         {
1317                 if (m_baseParams.gatherType == GATHERTYPE_OFFSET)
1318                 {
1319                         const GatherArgs&       gatherArgs              = getGatherArgs(m_currentIteration);
1320                         addUniform(binding++, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::IVec2), gatherArgs.offsets[0].getPtr());
1321                 }
1322                 else if (m_baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC)
1323                 {
1324                         const IVec2&            offsetRange             = getOffsetRange(m_baseParams.offsetSize, m_context.getDeviceProperties().limits);
1325                         addUniform(binding++, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::IVec2), offsetRange.getPtr());
1326                 }
1327                 else
1328                         DE_ASSERT(false);
1329         }
1330 }
1331
1332 template <typename TexViewT, typename TexCoordT>
1333 bool TextureGatherInstance::verify (const ConstPixelBufferAccess&       rendered,
1334                                                                 const TexViewT&                                 texture,
1335                                                                 const TexCoordT                                 (&texCoords)[4],
1336                                                                 const GatherArgs&                               gatherArgs) const
1337 {
1338         TestLog& log = m_context.getTestContext().getLog();
1339
1340         {
1341                 DE_ASSERT(m_colorBufferFormat.order == tcu::TextureFormat::RGBA);
1342                 DE_ASSERT(m_colorBufferFormat.type == tcu::TextureFormat::UNORM_INT8            ||
1343                                   m_colorBufferFormat.type == tcu::TextureFormat::UNSIGNED_INT8         ||
1344                                   m_colorBufferFormat.type == tcu::TextureFormat::SIGNED_INT8);
1345
1346                 const MovePtr<PixelOffsets>             pixelOffsets    = makePixelOffsetsFunctor(m_baseParams.gatherType, gatherArgs, getOffsetRange(m_baseParams.offsetSize, m_context.getDeviceProperties().limits));
1347                 const tcu::PixelFormat                  pixelFormat             = tcu::PixelFormat(8,8,8,8);
1348                 const IVec4                                             colorBits               = tcu::max(TextureTestUtil::getBitsVec(pixelFormat) - 1, tcu::IVec4(0));
1349                 const IVec3                                             coordBits               = m_baseParams.textureType == TEXTURETYPE_2D                    ? IVec3(20,20,0)
1350                                                                                                                 : m_baseParams.textureType == TEXTURETYPE_CUBE                  ? IVec3(10,10,10)
1351                                                                                                                 : m_baseParams.textureType == TEXTURETYPE_2D_ARRAY              ? IVec3(20,20,20)
1352                                                                                                                 : IVec3(-1);
1353                 const IVec3                                             uvwBits                 = m_baseParams.textureType == TEXTURETYPE_2D                    ? IVec3(7,7,0)
1354                                                                                                                 : m_baseParams.textureType == TEXTURETYPE_CUBE                  ? IVec3(6,6,0)
1355                                                                                                                 : m_baseParams.textureType == TEXTURETYPE_2D_ARRAY              ? IVec3(7,7,7)
1356                                                                                                                 : IVec3(-1);
1357                 tcu::Sampler                                    sampler;
1358                 sampler.wrapS           = m_baseParams.wrapS;
1359                 sampler.wrapT           = m_baseParams.wrapT;
1360                 sampler.compare         = m_baseParams.shadowCompareMode;
1361
1362                 if (isDepthFormat(m_baseParams.textureFormat))
1363                 {
1364                         tcu::TexComparePrecision comparePrec;
1365                         comparePrec.coordBits           = coordBits;
1366                         comparePrec.uvwBits                     = uvwBits;
1367                         comparePrec.referenceBits       = 16;
1368                         comparePrec.resultBits          = pixelFormat.redBits-1;
1369
1370                         return verifyGatherOffsetsCompare(log, rendered, texture, texCoords, sampler, comparePrec, PixelCompareRefZDefault(RENDER_SIZE), *pixelOffsets);
1371                 }
1372                 else
1373                 {
1374                         const int componentNdx = de::max(0, gatherArgs.componentNdx);
1375
1376                         if (isUnormFormatType(m_baseParams.textureFormat.type))
1377                         {
1378                                 tcu::LookupPrecision lookupPrec;
1379                                 lookupPrec.colorThreshold       = tcu::computeFixedPointThreshold(colorBits);
1380                                 lookupPrec.coordBits            = coordBits;
1381                                 lookupPrec.uvwBits                      = uvwBits;
1382                                 lookupPrec.colorMask            = TextureTestUtil::getCompareMask(pixelFormat);
1383                                 return verifyGatherOffsets<float>(log, rendered, texture, texCoords, sampler, lookupPrec, componentNdx, *pixelOffsets);
1384                         }
1385                         else if (isUIntFormatType(m_baseParams.textureFormat.type) || isSIntFormatType(m_baseParams.textureFormat.type))
1386                         {
1387                                 tcu::IntLookupPrecision         lookupPrec;
1388                                 lookupPrec.colorThreshold       = UVec4(0);
1389                                 lookupPrec.coordBits            = coordBits;
1390                                 lookupPrec.uvwBits                      = uvwBits;
1391                                 lookupPrec.colorMask            = TextureTestUtil::getCompareMask(pixelFormat);
1392
1393                                 if (isUIntFormatType(m_baseParams.textureFormat.type))
1394                                         return verifyGatherOffsets<deUint32>(log, rendered, texture, texCoords, sampler, lookupPrec, componentNdx, *pixelOffsets);
1395                                 else if (isSIntFormatType(m_baseParams.textureFormat.type))
1396                                         return verifyGatherOffsets<deInt32>(log, rendered, texture, texCoords, sampler, lookupPrec, componentNdx, *pixelOffsets);
1397                                 else
1398                                 {
1399                                         DE_ASSERT(false);
1400                                         return false;
1401                                 }
1402                         }
1403                         else
1404                         {
1405                                 DE_ASSERT(false);
1406                                 return false;
1407                         }
1408                 }
1409         }
1410 }
1411
1412 glu::VertexSource genVertexShaderSource (bool requireGpuShader5, int numTexCoordComponents, bool useNormalizedCoordInput)
1413 {
1414         DE_ASSERT(numTexCoordComponents == 2 || numTexCoordComponents == 3);
1415
1416         const string            texCoordType    = "vec" + de::toString(numTexCoordComponents);
1417         std::ostringstream      vert;
1418
1419         vert << "#version 310 es\n";
1420
1421         if (requireGpuShader5)
1422                 vert << "#extension GL_EXT_gpu_shader5 : require\n";
1423
1424         vert << "\n"
1425                         "layout (location = 0) in highp vec2 a_position;\n"
1426                         "layout (location = 1) in highp " << texCoordType << " a_texCoord;\n";
1427
1428         if (useNormalizedCoordInput)
1429                 vert << "layout (location = 2) in highp vec2 a_normalizedCoord; // (0,0) to (1,1)\n";
1430
1431         vert << "\n"
1432                         "layout (location = 0) out highp " << texCoordType << " v_texCoord;\n";
1433
1434         if (useNormalizedCoordInput)
1435                 vert << "layout (location = 1) out highp vec2 v_normalizedCoord;\n";
1436
1437         vert << "\n"
1438                         "void main (void)\n"
1439                         "{\n"
1440                         "       gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0);\n"
1441                         "       v_texCoord = a_texCoord;\n";
1442
1443         if (useNormalizedCoordInput)
1444                 vert << "       v_normalizedCoord = a_normalizedCoord;\n";
1445
1446         vert << "}\n";
1447
1448         return glu::VertexSource(vert.str());
1449 }
1450
1451 glu::FragmentSource genFragmentShaderSource (bool                                       requireGpuShader5,
1452                                                                                          int                                    numTexCoordComponents,
1453                                                                                          glu::DataType                  samplerType,
1454                                                                                          const string&                  funcCall,
1455                                                                                          bool                                   useNormalizedCoordInput,
1456                                                                                          bool                                   usePixCoord,
1457                                                                                          OffsetSize                             offsetSize,
1458                                                                                          const ImageBackingMode sparseCase)
1459 {
1460         DE_ASSERT(glu::isDataTypeSampler(samplerType));
1461         DE_ASSERT(de::inRange(numTexCoordComponents, 2, 3));
1462         DE_ASSERT(!usePixCoord || useNormalizedCoordInput);
1463
1464         const string            texCoordType    = "vec" + de::toString(numTexCoordComponents);
1465         deUint32                        binding                 = 0;
1466         std::ostringstream      frag;
1467         const string            outType                 = glu::getDataTypeName(getSamplerGatherResultType(samplerType));
1468
1469         if (sparseCase == ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE)
1470                 frag    << "#version 450\n"
1471                                 << "#extension GL_ARB_sparse_texture2 : require\n";
1472         else
1473                 frag << "#version 310 es\n";
1474
1475         if (requireGpuShader5)
1476                 frag << "#extension GL_EXT_gpu_shader5 : require\n";
1477
1478         frag << "\n"
1479                         "layout (location = 0) out mediump " << outType << " o_color;\n"
1480                         "\n"
1481                         "layout (location = 0) in highp " << texCoordType << " v_texCoord;\n";
1482
1483         if (useNormalizedCoordInput)
1484                 frag << "layout (location = 1) in highp vec2 v_normalizedCoord;\n";
1485
1486         frag << "\n"
1487                         "layout (binding = " << binding++ << ") uniform highp " << glu::getDataTypeName(samplerType) << " u_sampler;\n";
1488
1489         if (usePixCoord)
1490                 frag << "layout (binding = " << binding++ << ") uniform viewportSize { highp vec2 u_viewportSize; };\n";
1491
1492         if (offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
1493                 frag << "layout (binding = " << binding++ << ") uniform offset { highp ivec2 u_offset; };\n";
1494
1495         frag << "\n"
1496                         "void main(void)\n"
1497                         "{\n";
1498
1499         if (usePixCoord)
1500                 frag << "       ivec2 pixCoord = ivec2(v_normalizedCoord*u_viewportSize);\n";
1501
1502         if (sparseCase == ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE)
1503         {
1504                 // Texel declaration
1505                 frag << "\t" << outType << " texel;\n";
1506                 frag << "\tint success = " << funcCall << ";\n";
1507
1508                 // Check sparse validity, and handle each case
1509                 frag << "\tif (sparseTexelsResidentARB(success))\n"
1510                          << "\t\to_color = texel;\n"
1511                          <<     "\telse\n"
1512                          << "\t\to_color = " << outType << "(0.0, 0.0, 0.0, 1.0);\n";
1513         }
1514         else
1515         {
1516                 frag << "\t\to_color = " << funcCall << ";\n";
1517         }
1518
1519         frag << "}\n";
1520
1521         return glu::FragmentSource(frag.str());
1522 }
1523
1524 string genGatherFuncCall (GatherType                            gatherType,
1525                                                   const tcu::TextureFormat&     textureFormat,
1526                                                   const GatherArgs&                     gatherArgs,
1527                                                   const string&                         refZExpr,
1528                                                   const IVec2&                          offsetRange,
1529                                                   int                                           indentationDepth,
1530                                                   OffsetSize                            offsetSize,
1531                                                   const ImageBackingMode        sparseCase)
1532 {
1533         string result;
1534
1535         if (sparseCase == ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE)
1536         {
1537                 switch (gatherType)
1538                 {
1539                         case GATHERTYPE_BASIC:
1540                                 result += "sparseTextureGatherARB";
1541                                 break;
1542                         case GATHERTYPE_OFFSET: // \note Fallthrough.
1543                         case GATHERTYPE_OFFSET_DYNAMIC:
1544                                 result += "sparseTextureGatherOffsetARB";
1545                                 break;
1546                         case GATHERTYPE_OFFSETS:
1547                                 result += "sparseTextureGatherOffsetsARB";
1548                                 break;
1549                         default:
1550                                 DE_ASSERT(false);
1551                 }
1552         }
1553         else
1554         {
1555                 switch (gatherType)
1556                 {
1557                         case GATHERTYPE_BASIC:
1558                                 result += "textureGather";
1559                                 break;
1560                         case GATHERTYPE_OFFSET: // \note Fallthrough.
1561                         case GATHERTYPE_OFFSET_DYNAMIC:
1562                                 result += "textureGatherOffset";
1563                                 break;
1564                         case GATHERTYPE_OFFSETS:
1565                                 result += "textureGatherOffsets";
1566                                 break;
1567                         default:
1568                                 DE_ASSERT(false);
1569                 }
1570         }
1571
1572         result += "(u_sampler, v_texCoord";
1573
1574         if (isDepthFormat(textureFormat))
1575         {
1576                 DE_ASSERT(gatherArgs.componentNdx < 0);
1577                 result += ", " + refZExpr;
1578         }
1579
1580         if (gatherType == GATHERTYPE_OFFSET ||
1581                 gatherType == GATHERTYPE_OFFSET_DYNAMIC ||
1582                 gatherType == GATHERTYPE_OFFSETS)
1583         {
1584                 result += ", ";
1585                 switch (gatherType)
1586                 {
1587                         case GATHERTYPE_OFFSET:
1588                                 if (offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
1589                                         result += "u_offset";
1590                                 else
1591                                         result += "ivec2" + de::toString(gatherArgs.offsets[0]);
1592                                 break;
1593
1594                         case GATHERTYPE_OFFSET_DYNAMIC:
1595                                 if (offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
1596                                         result += "pixCoord.yx % ivec2(u_offset.y - u_offset.x + 1) + u_offset.x";
1597                                 else
1598                                         result += "pixCoord.yx % ivec2(" + de::toString(offsetRange.y() - offsetRange.x() + 1) + ") + " + de::toString(offsetRange.x());
1599                                 break;
1600
1601                         case GATHERTYPE_OFFSETS:
1602                                 DE_ASSERT(offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM);
1603                                 result += "ivec2[4](\n"
1604                                                   + string(indentationDepth, '\t') + "\tivec2" + de::toString(gatherArgs.offsets[0]) + ",\n"
1605                                                   + string(indentationDepth, '\t') + "\tivec2" + de::toString(gatherArgs.offsets[1]) + ",\n"
1606                                                   + string(indentationDepth, '\t') + "\tivec2" + de::toString(gatherArgs.offsets[2]) + ",\n"
1607                                                   + string(indentationDepth, '\t') + "\tivec2" + de::toString(gatherArgs.offsets[3]) + ")\n"
1608                                                   + string(indentationDepth, '\t') + "\t";
1609                                 break;
1610
1611                         default:
1612                                 DE_ASSERT(false);
1613                 }
1614         }
1615
1616         if (sparseCase == ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE)
1617                 result += ", texel";
1618
1619         if (gatherArgs.componentNdx >= 0)
1620         {
1621                 DE_ASSERT(gatherArgs.componentNdx < 4);
1622                 result += ", " + de::toString(gatherArgs.componentNdx);
1623         }
1624
1625         result += ")";
1626
1627         return result;
1628 }
1629
1630 // \todo [2016-07-08 pyry] Re-use programs if sources are identical
1631
1632 void genGatherPrograms (vk::SourceCollections& programCollection, const GatherCaseBaseParams& baseParams, const vector<GatherArgs>& iterations)
1633 {
1634         const int                                       numIterations           = (int)iterations.size();
1635         const string                            refZExpr                        = "v_normalizedCoord.x";
1636         const IVec2&                            offsetRange                     = baseParams.offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? getOffsetRange(baseParams.offsetSize) : IVec2(0);
1637         const bool                                      usePixCoord                     = baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC;
1638         const bool                                      useNormalizedCoord      = usePixCoord || isDepthFormat(baseParams.textureFormat);
1639         const bool                                      isDynamicOffset         = baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC;
1640         const bool                                      isShadow                        = isDepthFormat(baseParams.textureFormat);
1641         const glu::DataType                     samplerType                     = getSamplerType(baseParams.textureType, baseParams.textureFormat);
1642         const int                                       numDims                         = getNumTextureSamplingDimensions(baseParams.textureType);
1643         glu::VertexSource                       vert                            = genVertexShaderSource(requireGpuShader5(baseParams.gatherType, baseParams.offsetSize), numDims, isDynamicOffset || isShadow);
1644
1645         programCollection.glslSources.add("vert") << vert;
1646
1647         for (int iterNdx = 0; iterNdx < numIterations; iterNdx++)
1648         {
1649                 const GatherArgs&               gatherArgs                      = iterations[iterNdx];
1650                 const string                    funcCall                        = genGatherFuncCall(baseParams.gatherType, baseParams.textureFormat, gatherArgs, refZExpr, offsetRange, 1, baseParams.offsetSize, baseParams.sparseCase);
1651                 glu::FragmentSource             frag                            = genFragmentShaderSource(requireGpuShader5(baseParams.gatherType, baseParams.offsetSize), numDims, samplerType, funcCall, useNormalizedCoord, usePixCoord, baseParams.offsetSize, baseParams.sparseCase);
1652
1653                 programCollection.glslSources.add("frag_" + de::toString(iterNdx)) << frag;
1654         }
1655 }
1656
1657 // 2D
1658
1659 class TextureGather2DInstance : public TextureGatherInstance
1660 {
1661 public:
1662                                                                         TextureGather2DInstance                         (Context&                                               context,
1663                                                                                                                                                  const GatherCaseBaseParams&    baseParams,
1664                                                                                                                                                  const IVec2&                                   textureSize,
1665                                                                                                                                                  const vector<GatherArgs>&              iterations);
1666         virtual                                                 ~TextureGather2DInstance                        (void);
1667
1668 protected:
1669         virtual int                                             getNumIterations                                        (void) const                            { return (int)m_iterations.size();      }
1670         virtual GatherArgs                              getGatherArgs                                           (int iterationNdx) const        { return m_iterations[iterationNdx];}
1671
1672         virtual TextureBindingSp                createTexture                                           (void);
1673         virtual vector<float>                   computeQuadTexCoord                                     (int iterationNdx) const;
1674         virtual bool                                    verify                                                          (int iterationNdx, const ConstPixelBufferAccess& rendered) const;
1675
1676 private:
1677         const IVec2                                             m_textureSize;
1678         const vector<GatherArgs>                m_iterations;
1679
1680         tcu::Texture2D                                  m_swizzledTexture;
1681 };
1682
1683 TextureGather2DInstance::TextureGather2DInstance (Context&                                              context,
1684                                                                                                   const GatherCaseBaseParams&   baseParams,
1685                                                                                                   const IVec2&                                  textureSize,
1686                                                                                                   const vector<GatherArgs>&             iterations)
1687         : TextureGatherInstance         (context, baseParams)
1688         , m_textureSize                         (textureSize)
1689         , m_iterations                          (iterations)
1690         , m_swizzledTexture                     (tcu::TextureFormat(), 1, 1)
1691 {
1692         init();
1693 }
1694
1695 TextureGather2DInstance::~TextureGather2DInstance (void)
1696 {
1697 }
1698
1699 vector<float> TextureGather2DInstance::computeQuadTexCoord (int /* iterationNdx */) const
1700 {
1701         vector<float> res;
1702         TextureTestUtil::computeQuadTexCoord2D(res, Vec2(-0.3f, -0.4f), Vec2(1.5f, 1.6f));
1703         return res;
1704 }
1705
1706 TextureBindingSp TextureGather2DInstance::createTexture (void)
1707 {
1708         TestLog&                                                log                     = m_context.getTestContext().getLog();
1709         const tcu::TextureFormatInfo    texFmtInfo      = tcu::getTextureFormatInfo(m_baseParams.textureFormat);
1710         MovePtr<tcu::Texture2D>                 texture         = MovePtr<tcu::Texture2D>(new tcu::Texture2D(m_baseParams.textureFormat, m_textureSize.x(), m_textureSize.y()));
1711         const tcu::Sampler                              sampler         (m_baseParams.wrapS, m_baseParams.wrapT, tcu::Sampler::REPEAT_GL,
1712                                                                                                  m_baseParams.minFilter, m_baseParams.magFilter,
1713                                                                                                  0.0f /* LOD threshold */, true /* normalized coords */, m_baseParams.shadowCompareMode);
1714
1715         {
1716                 const int       levelBegin      = m_baseParams.baseLevel;
1717                 const int       levelEnd        = texture->getNumLevels();
1718                 DE_ASSERT(m_baseParams.baseLevel < texture->getNumLevels());
1719
1720                 for (int levelNdx = levelBegin; levelNdx < levelEnd; levelNdx++)
1721                 {
1722                         texture->allocLevel(levelNdx);
1723                         const PixelBufferAccess& level = texture->getLevel(levelNdx);
1724                         fillWithRandomColorTiles(level, texFmtInfo.valueMin, texFmtInfo.valueMax, (deUint32)m_context.getTestContext().getCommandLine().getBaseSeed());
1725                         log << TestLog::Image("InputTextureLevel" + de::toString(levelNdx), "Input texture, level " + de::toString(levelNdx), level)
1726                                 << TestLog::Message << "Note: texture level's size is " << IVec2(level.getWidth(), level.getHeight()) << TestLog::EndMessage;
1727                 }
1728
1729                 swizzleTexture(m_swizzledTexture, *texture, m_baseParams.textureSwizzle);
1730         }
1731
1732         return TextureBindingSp(new TextureBinding(texture.release(), sampler));
1733 }
1734
1735 bool TextureGather2DInstance::verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const
1736 {
1737         Vec2 texCoords[4];
1738         computeTexCoordVecs(computeQuadTexCoord(iterationNdx), texCoords);
1739         return TextureGatherInstance::verify(rendered, getOneLevelSubView(tcu::Texture2DView(m_swizzledTexture), m_baseParams.baseLevel), texCoords, m_iterations[iterationNdx]);
1740 }
1741
1742 class TextureGather2DCase : public TestCase
1743 {
1744 public:
1745                                                                         TextureGather2DCase                                     (tcu::TestContext&                                      testCtx,
1746                                                                                                                                                  const string&                                          name,
1747                                                                                                                                                  const string&                                          description,
1748                                                                                                                                                  const GatherType                                       gatherType,
1749                                                                                                                                                  const OffsetSize                                       offsetSize,
1750                                                                                                                                                  const tcu::TextureFormat                       textureFormat,
1751                                                                                                                                                  const tcu::Sampler::CompareMode        shadowCompareMode,
1752                                                                                                                                                  const tcu::Sampler::WrapMode           wrapS,
1753                                                                                                                                                  const tcu::Sampler::WrapMode           wrapT,
1754                                                                                                                                                  const MaybeTextureSwizzle&                     textureSwizzle,
1755                                                                                                                                                  const tcu::Sampler::FilterMode         minFilter,
1756                                                                                                                                                  const tcu::Sampler::FilterMode         magFilter,
1757                                                                                                                                                  const int                                                      baseLevel,
1758                                                                                                                                                  const deUint32                                         flags,
1759                                                                                                                                                  const IVec2&                                           textureSize,
1760                                                                                                                                                  const ImageBackingMode                         sparseCase);
1761         virtual                                                 ~TextureGather2DCase                            (void);
1762
1763         virtual void                                    initPrograms                                            (vk::SourceCollections& dst) const;
1764         virtual TestInstance*                   createInstance                                          (Context& context) const;
1765
1766 private:
1767         const GatherCaseBaseParams              m_baseParams;
1768         const IVec2                                             m_textureSize;
1769 };
1770
1771 TextureGather2DCase::TextureGather2DCase (tcu::TestContext&                                             testCtx,
1772                                                                                   const string&                                                 name,
1773                                                                                   const string&                                                 description,
1774                                                                                   const GatherType                                              gatherType,
1775                                                                                   const OffsetSize                                              offsetSize,
1776                                                                                   const tcu::TextureFormat                              textureFormat,
1777                                                                                   const tcu::Sampler::CompareMode               shadowCompareMode,
1778                                                                                   const tcu::Sampler::WrapMode                  wrapS,
1779                                                                                   const tcu::Sampler::WrapMode                  wrapT,
1780                                                                                   const MaybeTextureSwizzle&                    textureSwizzle,
1781                                                                                   const tcu::Sampler::FilterMode                minFilter,
1782                                                                                   const tcu::Sampler::FilterMode                magFilter,
1783                                                                                   const int                                                             baseLevel,
1784                                                                                   const deUint32                                                flags,
1785                                                                                   const IVec2&                                                  textureSize,
1786                                                                                   const ImageBackingMode                                sparseCase)
1787         : TestCase              (testCtx, name, description)
1788         , m_baseParams  (TEXTURETYPE_2D, gatherType, offsetSize, textureFormat, shadowCompareMode, wrapS, wrapT, textureSwizzle, minFilter, magFilter, baseLevel, flags, sparseCase)
1789         , m_textureSize (textureSize)
1790 {
1791 }
1792
1793 TextureGather2DCase::~TextureGather2DCase (void)
1794 {
1795 }
1796
1797 void TextureGather2DCase::initPrograms (vk::SourceCollections& dst) const
1798 {
1799         const vector<GatherArgs>        iterations      = generateBasic2DCaseIterations(m_baseParams.gatherType,
1800                                                                                                                                                         m_baseParams.textureFormat,
1801                                                                                                                                                         m_baseParams.offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? getOffsetRange(m_baseParams.offsetSize) : IVec2(0));
1802
1803         genGatherPrograms(dst, m_baseParams, iterations);
1804 }
1805
1806 TestInstance* TextureGather2DCase::createInstance (Context& context) const
1807 {
1808         const vector<GatherArgs>        iterations      = generateBasic2DCaseIterations(m_baseParams.gatherType,
1809                                                                                                                                                         m_baseParams.textureFormat,
1810                                                                                                                                                         getOffsetRange(m_baseParams.offsetSize, context.getDeviceProperties().limits));
1811
1812         return new TextureGather2DInstance(context, m_baseParams, m_textureSize, iterations);
1813 }
1814
1815 // 2D array
1816
1817 struct Gather2DArrayArgs
1818 {
1819         GatherArgs      gatherArgs;
1820         int                     layerNdx;
1821
1822         operator GatherArgs() const { return gatherArgs; }
1823 };
1824
1825 vector<Gather2DArrayArgs> generate2DArrayCaseIterations (GatherType                                     gatherType,
1826                                                                                                                  const tcu::TextureFormat&      textureFormat,
1827                                                                                                                  const IVec2&                           offsetRange,
1828                                                                                                                  const IVec3&                           textureSize)
1829 {
1830         const vector<GatherArgs>        basicIterations = generateBasic2DCaseIterations(gatherType, textureFormat, offsetRange);
1831         vector<Gather2DArrayArgs>       iterations;
1832
1833         // \note Out-of-bounds layer indices are tested too.
1834         for (int layerNdx = -1; layerNdx < textureSize.z()+1; layerNdx++)
1835         {
1836                 // Don't duplicate all cases for all layers.
1837                 if (layerNdx == 0)
1838                 {
1839                         for (int basicNdx = 0; basicNdx < (int)basicIterations.size(); basicNdx++)
1840                         {
1841                                 iterations.push_back(Gather2DArrayArgs());
1842                                 iterations.back().gatherArgs = basicIterations[basicNdx];
1843                                 iterations.back().layerNdx = layerNdx;
1844                         }
1845                 }
1846                 else
1847                 {
1848                         // For other layers than 0, only test one component and one set of offsets per layer.
1849                         for (int basicNdx = 0; basicNdx < (int)basicIterations.size(); basicNdx++)
1850                         {
1851                                 if (isDepthFormat(textureFormat) || basicIterations[basicNdx].componentNdx == (layerNdx + 2) % 4)
1852                                 {
1853                                         iterations.push_back(Gather2DArrayArgs());
1854                                         iterations.back().gatherArgs = basicIterations[basicNdx];
1855                                         iterations.back().layerNdx = layerNdx;
1856                                         break;
1857                                 }
1858                         }
1859                 }
1860         }
1861
1862         return iterations;
1863 }
1864
1865 class TextureGather2DArrayInstance : public TextureGatherInstance
1866 {
1867 public:
1868                                                                         TextureGather2DArrayInstance            (Context&                                                       context,
1869                                                                                                                                                  const GatherCaseBaseParams&            baseParams,
1870                                                                                                                                                  const IVec3&                                           textureSize,
1871                                                                                                                                                  const vector<Gather2DArrayArgs>&       iterations);
1872         virtual                                                 ~TextureGather2DArrayInstance           (void);
1873
1874 protected:
1875         virtual int                                             getNumIterations                                        (void) const                            { return (int)m_iterations.size();                              }
1876         virtual GatherArgs                              getGatherArgs                                           (int iterationNdx) const        { return m_iterations[iterationNdx].gatherArgs; }
1877
1878         virtual TextureBindingSp                createTexture                                           (void);
1879         virtual vector<float>                   computeQuadTexCoord                                     (int iterationNdx) const;
1880         virtual bool                                    verify                                                          (int iterationNdx, const ConstPixelBufferAccess& rendered) const;
1881
1882 private:
1883         const IVec3                                             m_textureSize;
1884         const vector<Gather2DArrayArgs> m_iterations;
1885
1886         tcu::Texture2DArray                             m_swizzledTexture;
1887 };
1888
1889 TextureGather2DArrayInstance::TextureGather2DArrayInstance (Context&                                                    context,
1890                                                                                                                         const GatherCaseBaseParams&                     baseParams,
1891                                                                                                                         const IVec3&                                            textureSize,
1892                                                                                                                         const vector<Gather2DArrayArgs>&        iterations)
1893         : TextureGatherInstance         (context, baseParams)
1894         , m_textureSize                         (textureSize)
1895         , m_iterations                          (iterations)
1896         , m_swizzledTexture                     (tcu::TextureFormat(), 1, 1, 1)
1897 {
1898         init();
1899 }
1900
1901 TextureGather2DArrayInstance::~TextureGather2DArrayInstance (void)
1902 {
1903 }
1904
1905 vector<float> TextureGather2DArrayInstance::computeQuadTexCoord (int iterationNdx) const
1906 {
1907         vector<float> res;
1908         TextureTestUtil::computeQuadTexCoord2DArray(res, m_iterations[iterationNdx].layerNdx, Vec2(-0.3f, -0.4f), Vec2(1.5f, 1.6f));
1909         return res;
1910 }
1911
1912 TextureBindingSp TextureGather2DArrayInstance::createTexture (void)
1913 {
1914         TestLog&                                                log                     = m_context.getTestContext().getLog();
1915         const tcu::TextureFormatInfo    texFmtInfo      = tcu::getTextureFormatInfo(m_baseParams.textureFormat);
1916         MovePtr<tcu::Texture2DArray>    texture         = MovePtr<tcu::Texture2DArray>(new tcu::Texture2DArray(m_baseParams.textureFormat, m_textureSize.x(), m_textureSize.y(), m_textureSize.z()));
1917         const tcu::Sampler                              sampler         (m_baseParams.wrapS, m_baseParams.wrapT, tcu::Sampler::REPEAT_GL,
1918                                                                                                  m_baseParams.minFilter, m_baseParams.magFilter,
1919                                                                                                  0.0f /* LOD threshold */, true /* normalized coords */, m_baseParams.shadowCompareMode);
1920
1921         {
1922                 const int       levelBegin      = m_baseParams.baseLevel;
1923                 const int       levelEnd        = texture->getNumLevels();
1924                 DE_ASSERT(m_baseParams.baseLevel < texture->getNumLevels());
1925
1926                 for (int levelNdx = levelBegin; levelNdx < levelEnd; levelNdx++)
1927                 {
1928                         texture->allocLevel(levelNdx);
1929                         const PixelBufferAccess& level = texture->getLevel(levelNdx);
1930                         fillWithRandomColorTiles(level, texFmtInfo.valueMin, texFmtInfo.valueMax, (deUint32)m_context.getTestContext().getCommandLine().getBaseSeed());
1931
1932                         log << TestLog::ImageSet("InputTextureLevel", "Input texture, level " + de::toString(levelNdx));
1933                         for (int layerNdx = 0; layerNdx < m_textureSize.z(); layerNdx++)
1934                                 log << TestLog::Image("InputTextureLevel" + de::toString(layerNdx) + "Layer" + de::toString(layerNdx),
1935                                                                           "Layer " + de::toString(layerNdx),
1936                                                                           tcu::getSubregion(level, 0, 0, layerNdx, level.getWidth(), level.getHeight(), 1));
1937                         log << TestLog::EndImageSet
1938                                 << TestLog::Message << "Note: texture level's size is " << IVec3(level.getWidth(), level.getHeight(), level.getDepth()) << TestLog::EndMessage;
1939                 }
1940
1941                 swizzleTexture(m_swizzledTexture, *texture, m_baseParams.textureSwizzle);
1942         }
1943
1944         return TextureBindingSp(new TextureBinding(texture.release(), sampler));
1945 }
1946
1947 bool TextureGather2DArrayInstance::verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const
1948 {
1949         Vec3 texCoords[4];
1950         computeTexCoordVecs(computeQuadTexCoord(iterationNdx), texCoords);
1951         return TextureGatherInstance::verify(rendered, getOneLevelSubView(tcu::Texture2DArrayView(m_swizzledTexture), m_baseParams.baseLevel), texCoords, m_iterations[iterationNdx].gatherArgs);
1952 }
1953
1954 class TextureGather2DArrayCase : public TestCase
1955 {
1956 public:
1957                                                                         TextureGather2DArrayCase                        (tcu::TestContext&                                      testCtx,
1958                                                                                                                                                  const string&                                          name,
1959                                                                                                                                                  const string&                                          description,
1960                                                                                                                                                  const GatherType                                       gatherType,
1961                                                                                                                                                  const OffsetSize                                       offsetSize,
1962                                                                                                                                                  const tcu::TextureFormat                       textureFormat,
1963                                                                                                                                                  const tcu::Sampler::CompareMode        shadowCompareMode,
1964                                                                                                                                                  const tcu::Sampler::WrapMode           wrapS,
1965                                                                                                                                                  const tcu::Sampler::WrapMode           wrapT,
1966                                                                                                                                                  const MaybeTextureSwizzle&                     textureSwizzle,
1967                                                                                                                                                  const tcu::Sampler::FilterMode         minFilter,
1968                                                                                                                                                  const tcu::Sampler::FilterMode         magFilter,
1969                                                                                                                                                  const int                                                      baseLevel,
1970                                                                                                                                                  const deUint32                                         flags,
1971                                                                                                                                                  const IVec3&                                           textureSize,
1972                                                                                                                                                  const ImageBackingMode                         sparseCase);
1973         virtual                                                 ~TextureGather2DArrayCase                       (void);
1974
1975         virtual void                                    initPrograms                                            (vk::SourceCollections& dst) const;
1976         virtual TestInstance*                   createInstance                                          (Context& context) const;
1977
1978 private:
1979         const GatherCaseBaseParams              m_baseParams;
1980         const IVec3                                             m_textureSize;
1981 };
1982
1983 TextureGather2DArrayCase::TextureGather2DArrayCase (tcu::TestContext&                                   testCtx,
1984                                                                                                         const string&                                           name,
1985                                                                                                         const string&                                           description,
1986                                                                                                         const GatherType                                        gatherType,
1987                                                                                                         const OffsetSize                                        offsetSize,
1988                                                                                                         const tcu::TextureFormat                        textureFormat,
1989                                                                                                         const tcu::Sampler::CompareMode         shadowCompareMode,
1990                                                                                                         const tcu::Sampler::WrapMode            wrapS,
1991                                                                                                         const tcu::Sampler::WrapMode            wrapT,
1992                                                                                                         const MaybeTextureSwizzle&                      textureSwizzle,
1993                                                                                                         const tcu::Sampler::FilterMode          minFilter,
1994                                                                                                         const tcu::Sampler::FilterMode          magFilter,
1995                                                                                                         const int                                                       baseLevel,
1996                                                                                                         const deUint32                                          flags,
1997                                                                                                         const IVec3&                                            textureSize,
1998                                                                                                         const ImageBackingMode                          sparseCase)
1999         : TestCase                      (testCtx, name, description)
2000         , m_baseParams          (TEXTURETYPE_2D_ARRAY, gatherType, offsetSize, textureFormat, shadowCompareMode, wrapS, wrapT, textureSwizzle, minFilter, magFilter, baseLevel, flags, sparseCase)
2001         , m_textureSize         (textureSize)
2002 {
2003 }
2004
2005 TextureGather2DArrayCase::~TextureGather2DArrayCase (void)
2006 {
2007 }
2008
2009 void TextureGather2DArrayCase::initPrograms (vk::SourceCollections& dst) const
2010 {
2011         const vector<Gather2DArrayArgs>         iterations      = generate2DArrayCaseIterations(m_baseParams.gatherType,
2012                                                                                                                                                                         m_baseParams.textureFormat,
2013                                                                                                                                                                         m_baseParams.offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? getOffsetRange(m_baseParams.offsetSize) : IVec2(0),
2014                                                                                                                                                                         m_textureSize);
2015
2016         genGatherPrograms(dst, m_baseParams, vector<GatherArgs>(iterations.begin(), iterations.end()));
2017 }
2018
2019 TestInstance* TextureGather2DArrayCase::createInstance (Context& context) const
2020 {
2021         const vector<Gather2DArrayArgs>         iterations      = generate2DArrayCaseIterations(m_baseParams.gatherType,
2022                                                                                                                                                                         m_baseParams.textureFormat,
2023                                                                                                                                                                         getOffsetRange(m_baseParams.offsetSize, context.getDeviceProperties().limits),
2024                                                                                                                                                                         m_textureSize);
2025
2026         return new TextureGather2DArrayInstance(context, m_baseParams, m_textureSize, iterations);
2027 }
2028
2029 // Cube
2030
2031 struct GatherCubeArgs
2032 {
2033         GatherArgs              gatherArgs;
2034         tcu::CubeFace   face;
2035
2036         operator GatherArgs() const { return gatherArgs; }
2037 };
2038
2039 vector<GatherCubeArgs> generateCubeCaseIterations (GatherType gatherType, const tcu::TextureFormat& textureFormat, const IVec2& offsetRange)
2040 {
2041         const vector<GatherArgs>        basicIterations = generateBasic2DCaseIterations(gatherType, textureFormat, offsetRange);
2042         vector<GatherCubeArgs>          iterations;
2043
2044         for (int cubeFaceI = 0; cubeFaceI < tcu::CUBEFACE_LAST; cubeFaceI++)
2045         {
2046                 const tcu::CubeFace cubeFace = (tcu::CubeFace)cubeFaceI;
2047
2048                 // Don't duplicate all cases for all faces.
2049                 if (cubeFaceI == 0)
2050                 {
2051                         for (int basicNdx = 0; basicNdx < (int)basicIterations.size(); basicNdx++)
2052                         {
2053                                 iterations.push_back(GatherCubeArgs());
2054                                 iterations.back().gatherArgs = basicIterations[basicNdx];
2055                                 iterations.back().face = cubeFace;
2056                         }
2057                 }
2058                 else
2059                 {
2060                         // For other faces than first, only test one component per face.
2061                         for (int basicNdx = 0; basicNdx < (int)basicIterations.size(); basicNdx++)
2062                         {
2063                                 if (isDepthFormat(textureFormat) || basicIterations[basicNdx].componentNdx == cubeFaceI % 4)
2064                                 {
2065                                         iterations.push_back(GatherCubeArgs());
2066                                         iterations.back().gatherArgs = basicIterations[basicNdx];
2067                                         iterations.back().face = cubeFace;
2068                                         break;
2069                                 }
2070                         }
2071                 }
2072         }
2073
2074         return iterations;
2075 }
2076
2077 class TextureGatherCubeInstance : public TextureGatherInstance
2078 {
2079 public:
2080                                                                         TextureGatherCubeInstance                       (Context&                                                       context,
2081                                                                                                                                                  const GatherCaseBaseParams&            baseParams,
2082                                                                                                                                                  const int                                                      textureSize,
2083                                                                                                                                                  const vector<GatherCubeArgs>&          iterations);
2084         virtual                                                 ~TextureGatherCubeInstance                      (void);
2085
2086 protected:
2087         virtual int                                             getNumIterations                                        (void) const                            { return (int)m_iterations.size();                              }
2088         virtual GatherArgs                              getGatherArgs                                           (int iterationNdx) const        { return m_iterations[iterationNdx].gatherArgs; }
2089
2090         virtual TextureBindingSp                createTexture                                           (void);
2091         virtual vector<float>                   computeQuadTexCoord                                     (int iterationNdx) const;
2092         virtual bool                                    verify                                                          (int iterationNdx, const ConstPixelBufferAccess& rendered) const;
2093
2094 private:
2095         const int                                               m_textureSize;
2096         const vector<GatherCubeArgs>    m_iterations;
2097
2098         tcu::TextureCube                                m_swizzledTexture;
2099 };
2100
2101 TextureGatherCubeInstance::TextureGatherCubeInstance (Context&                                                  context,
2102                                                                                                           const GatherCaseBaseParams&           baseParams,
2103                                                                                                           const int                                                     textureSize,
2104                                                                                                           const vector<GatherCubeArgs>&         iterations)
2105         : TextureGatherInstance         (context, baseParams)
2106         , m_textureSize                         (textureSize)
2107         , m_iterations                          (iterations)
2108         , m_swizzledTexture                     (tcu::TextureFormat(), 1)
2109 {
2110         init();
2111 }
2112
2113 TextureGatherCubeInstance::~TextureGatherCubeInstance (void)
2114 {
2115 }
2116
2117 vector<float> TextureGatherCubeInstance::computeQuadTexCoord (int iterationNdx) const
2118 {
2119         const bool              corners = (m_baseParams.flags & GATHERCASE_DONT_SAMPLE_CUBE_CORNERS) == 0;
2120         const Vec2              minC    = corners ? Vec2(-1.2f) : Vec2(-0.6f, -1.2f);
2121         const Vec2              maxC    = corners ? Vec2( 1.2f) : Vec2( 0.6f,  1.2f);
2122         vector<float>   res;
2123         TextureTestUtil::computeQuadTexCoordCube(res, m_iterations[iterationNdx].face, minC, maxC);
2124         return res;
2125 }
2126
2127 TextureBindingSp TextureGatherCubeInstance::createTexture (void)
2128 {
2129         TestLog&                                                log                     = m_context.getTestContext().getLog();
2130         const tcu::TextureFormatInfo    texFmtInfo      = tcu::getTextureFormatInfo(m_baseParams.textureFormat);
2131         MovePtr<tcu::TextureCube>               texture         = MovePtr<tcu::TextureCube>(new tcu::TextureCube(m_baseParams.textureFormat, m_textureSize));
2132         const tcu::Sampler                              sampler         (m_baseParams.wrapS, m_baseParams.wrapT, tcu::Sampler::REPEAT_GL,
2133                                                                                                  m_baseParams.minFilter, m_baseParams.magFilter,
2134                                                                                                  0.0f /* LOD threshold */, true /* normalized coords */, m_baseParams.shadowCompareMode,
2135                                                                                                  0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */);
2136
2137         {
2138                 const int       levelBegin      = m_baseParams.baseLevel;
2139                 const int       levelEnd        = texture->getNumLevels();
2140                 DE_ASSERT(m_baseParams.baseLevel < texture->getNumLevels());
2141
2142                 for (int levelNdx = levelBegin; levelNdx < levelEnd; levelNdx++)
2143                 {
2144                         log << TestLog::ImageSet("InputTextureLevel" + de::toString(levelNdx), "Input texture, level " + de::toString(levelNdx));
2145
2146                         for (int cubeFaceI = 0; cubeFaceI < tcu::CUBEFACE_LAST; cubeFaceI++)
2147                         {
2148                                 const tcu::CubeFace                     cubeFace        = (tcu::CubeFace)cubeFaceI;
2149                                 texture->allocLevel(cubeFace, levelNdx);
2150                                 const PixelBufferAccess&        levelFace       = texture->getLevelFace(levelNdx, cubeFace);
2151                                 fillWithRandomColorTiles(levelFace, texFmtInfo.valueMin, texFmtInfo.valueMax, (deUint32)m_context.getTestContext().getCommandLine().getBaseSeed() ^ (deUint32)cubeFaceI);
2152
2153                                 log << TestLog::Image("InputTextureLevel" + de::toString(levelNdx) + "Face" + de::toString((int)cubeFace), de::toString(cubeFace), levelFace);
2154                         }
2155
2156                         log << TestLog::EndImageSet
2157                                 << TestLog::Message << "Note: texture level's size is " << texture->getLevelFace(levelNdx, tcu::CUBEFACE_NEGATIVE_X).getWidth() << TestLog::EndMessage;
2158                 }
2159
2160                 swizzleTexture(m_swizzledTexture, *texture, m_baseParams.textureSwizzle);
2161         }
2162
2163         return TextureBindingSp(new TextureBinding(texture.release(), sampler));
2164 }
2165
2166 bool TextureGatherCubeInstance::verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const
2167 {
2168         Vec3 texCoords[4];
2169         computeTexCoordVecs(computeQuadTexCoord(iterationNdx), texCoords);
2170         return TextureGatherInstance::verify(rendered, getOneLevelSubView(tcu::TextureCubeView(m_swizzledTexture), m_baseParams.baseLevel), texCoords, m_iterations[iterationNdx].gatherArgs);
2171 }
2172
2173 // \note Cube case always uses just basic textureGather(); offset versions are not defined for cube maps.
2174 class TextureGatherCubeCase : public TestCase
2175 {
2176 public:
2177                                                                         TextureGatherCubeCase                           (tcu::TestContext&                                      testCtx,
2178                                                                                                                                                  const string&                                          name,
2179                                                                                                                                                  const string&                                          description,
2180                                                                                                                                                  const tcu::TextureFormat                       textureFormat,
2181                                                                                                                                                  const tcu::Sampler::CompareMode        shadowCompareMode,
2182                                                                                                                                                  const tcu::Sampler::WrapMode           wrapS,
2183                                                                                                                                                  const tcu::Sampler::WrapMode           wrapT,
2184                                                                                                                                                  const MaybeTextureSwizzle&                     textureSwizzle,
2185                                                                                                                                                  const tcu::Sampler::FilterMode         minFilter,
2186                                                                                                                                                  const tcu::Sampler::FilterMode         magFilter,
2187                                                                                                                                                  const int                                                      baseLevel,
2188                                                                                                                                                  const deUint32                                         flags,
2189                                                                                                                                                  const int                                                      textureSize,
2190                                                                                                                                                  const ImageBackingMode                         sparseCase);
2191         virtual                                                 ~TextureGatherCubeCase                          (void);
2192
2193         virtual void                                    initPrograms                                            (vk::SourceCollections& dst) const;
2194         virtual TestInstance*                   createInstance                                          (Context& context) const;
2195
2196 private:
2197         const GatherCaseBaseParams              m_baseParams;
2198         const int                                               m_textureSize;
2199 };
2200
2201 TextureGatherCubeCase::TextureGatherCubeCase (tcu::TestContext&                                         testCtx,
2202                                                                                           const string&                                                 name,
2203                                                                                           const string&                                                 description,
2204                                                                                           const tcu::TextureFormat                              textureFormat,
2205                                                                                           const tcu::Sampler::CompareMode               shadowCompareMode,
2206                                                                                           const tcu::Sampler::WrapMode                  wrapS,
2207                                                                                           const tcu::Sampler::WrapMode                  wrapT,
2208                                                                                           const MaybeTextureSwizzle&                    textureSwizzle,
2209                                                                                           const tcu::Sampler::FilterMode                minFilter,
2210                                                                                           const tcu::Sampler::FilterMode                magFilter,
2211                                                                                           const int                                                             baseLevel,
2212                                                                                           const deUint32                                                flags,
2213                                                                                           const int                                                             textureSize,
2214                                                                                           const ImageBackingMode                                sparseCase)
2215         : TestCase                      (testCtx, name, description)
2216         , m_baseParams          (TEXTURETYPE_CUBE, GATHERTYPE_BASIC, OFFSETSIZE_NONE, textureFormat, shadowCompareMode, wrapS, wrapT, textureSwizzle, minFilter, magFilter, baseLevel, flags, sparseCase)
2217         , m_textureSize         (textureSize)
2218 {
2219 }
2220
2221 TextureGatherCubeCase::~TextureGatherCubeCase (void)
2222 {
2223 }
2224
2225 void TextureGatherCubeCase::initPrograms (vk::SourceCollections& dst) const
2226 {
2227         const vector<GatherCubeArgs>    iterations      = generateCubeCaseIterations(m_baseParams.gatherType,
2228                                                                                                                                                          m_baseParams.textureFormat,
2229                                                                                                                                                          m_baseParams.offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? getOffsetRange(m_baseParams.offsetSize) : IVec2(0));
2230
2231         genGatherPrograms(dst, m_baseParams, vector<GatherArgs>(iterations.begin(), iterations.end()));
2232 }
2233
2234 TestInstance* TextureGatherCubeCase::createInstance (Context& context) const
2235 {
2236         const vector<GatherCubeArgs>    iterations      = generateCubeCaseIterations(m_baseParams.gatherType,
2237                                                                                                                                                          m_baseParams.textureFormat,
2238                                                                                                                                                          getOffsetRange(m_baseParams.offsetSize, context.getDeviceProperties().limits));
2239
2240         return new TextureGatherCubeInstance(context, m_baseParams, m_textureSize, iterations);
2241 }
2242
2243 class TextureGatherTests : public tcu::TestCaseGroup
2244 {
2245 public:
2246                                                                 TextureGatherTests                              (tcu::TestContext& context);
2247         virtual                                         ~TextureGatherTests                             (void);
2248         virtual void                            init                                                    (void);
2249
2250 private:
2251                                                                 TextureGatherTests                              (const TextureGatherTests&);            // not allowed!
2252         TextureGatherTests&                     operator=                                               (const TextureGatherTests&);            // not allowed!
2253 };
2254
2255 TextureGatherTests::TextureGatherTests (tcu::TestContext& context)
2256         : TestCaseGroup(context, "texture_gather", "textureGather* tests")
2257 {
2258 }
2259
2260 TextureGatherTests::~TextureGatherTests (void)
2261 {
2262 }
2263
2264 static inline TestCase* makeTextureGatherCase (TextureType                                      textureType,
2265                                                                                            tcu::TestContext&                    testCtx,
2266                                                                                            const string&                                name,
2267                                                                                            const string&                                description,
2268                                                                                            GatherType                                   gatherType,
2269                                                                                            OffsetSize                                   offsetSize,
2270                                                                                            tcu::TextureFormat                   textureFormat,
2271                                                                                            tcu::Sampler::CompareMode    shadowCompareMode,
2272                                                                                            tcu::Sampler::WrapMode               wrapS,
2273                                                                                            tcu::Sampler::WrapMode               wrapT,
2274                                                                                            const MaybeTextureSwizzle&   texSwizzle,
2275                                                                                            tcu::Sampler::FilterMode             minFilter,
2276                                                                                            tcu::Sampler::FilterMode             magFilter,
2277                                                                                            int                                                  baseLevel,
2278                                                                                            const IVec3&                                 textureSize,
2279                                                                                            deUint32                                             flags = 0,
2280                                                                                            const ImageBackingMode               sparseCase = ShaderRenderCaseInstance::IMAGE_BACKING_MODE_REGULAR)
2281 {
2282         switch (textureType)
2283         {
2284                 case TEXTURETYPE_2D:
2285                         return new TextureGather2DCase(testCtx, name, description, gatherType, offsetSize, textureFormat, shadowCompareMode,
2286                                                                                    wrapS, wrapT, texSwizzle, minFilter, magFilter, baseLevel, flags, textureSize.swizzle(0, 1), sparseCase);
2287
2288                 case TEXTURETYPE_2D_ARRAY:
2289                         return new TextureGather2DArrayCase(testCtx, name, description, gatherType, offsetSize, textureFormat, shadowCompareMode,
2290                                                                                                 wrapS, wrapT, texSwizzle, minFilter, magFilter, baseLevel, flags, textureSize, sparseCase);
2291
2292                 case TEXTURETYPE_CUBE:
2293                         DE_ASSERT(gatherType == GATHERTYPE_BASIC);
2294                         DE_ASSERT(offsetSize == OFFSETSIZE_NONE);
2295                         return new TextureGatherCubeCase(testCtx, name, description, textureFormat, shadowCompareMode,
2296                                                                                          wrapS, wrapT, texSwizzle, minFilter, magFilter, baseLevel, flags, textureSize.x(), sparseCase);
2297
2298                 default:
2299                         DE_ASSERT(false);
2300                         return DE_NULL;
2301         }
2302 }
2303
2304 static inline const char* compareModeName (tcu::Sampler::CompareMode mode)
2305 {
2306         switch (mode)
2307         {
2308                 case tcu::Sampler::COMPAREMODE_LESS:                            return "less";
2309                 case tcu::Sampler::COMPAREMODE_LESS_OR_EQUAL:           return "less_or_equal";
2310                 case tcu::Sampler::COMPAREMODE_GREATER:                         return "greater";
2311                 case tcu::Sampler::COMPAREMODE_GREATER_OR_EQUAL:        return "greater_or_equal";
2312                 case tcu::Sampler::COMPAREMODE_EQUAL:                           return "equal";
2313                 case tcu::Sampler::COMPAREMODE_NOT_EQUAL:                       return "not_equal";
2314                 case tcu::Sampler::COMPAREMODE_ALWAYS:                          return "always";
2315                 case tcu::Sampler::COMPAREMODE_NEVER:                           return "never";
2316                 default: DE_ASSERT(false); return DE_NULL;
2317         }
2318 }
2319
2320 void TextureGatherTests::init (void)
2321 {
2322         const struct
2323         {
2324                 const char* name;
2325                 TextureType type;
2326         } textureTypes[] =
2327         {
2328                 { "2d",                 TEXTURETYPE_2D                  },
2329                 { "2d_array",   TEXTURETYPE_2D_ARRAY    },
2330                 { "cube",               TEXTURETYPE_CUBE                }
2331         };
2332
2333         const struct
2334         {
2335                 const char*                     name;
2336                 tcu::TextureFormat      format;
2337         } formats[] =
2338         {
2339                 { "rgba8",              tcu::TextureFormat(tcu::TextureFormat::RGBA,    tcu::TextureFormat::UNORM_INT8)         },
2340                 { "rgba8ui",    tcu::TextureFormat(tcu::TextureFormat::RGBA,    tcu::TextureFormat::UNSIGNED_INT8)      },
2341                 { "rgba8i",             tcu::TextureFormat(tcu::TextureFormat::RGBA,    tcu::TextureFormat::SIGNED_INT8)        },
2342                 { "depth32f",   tcu::TextureFormat(tcu::TextureFormat::D,               tcu::TextureFormat::FLOAT)                      }
2343         };
2344
2345         const struct
2346         {
2347                 const char*             name;
2348                 IVec3                   size;
2349         } textureSizes[] =
2350         {
2351                 { "size_pot",   IVec3(64, 64, 3) },
2352                 { "size_npot",  IVec3(17, 23, 3) }
2353         };
2354
2355         const struct
2356         {
2357                 const char*                             name;
2358                 tcu::Sampler::WrapMode  mode;
2359         } wrapModes[] =
2360         {
2361                 { "clamp_to_edge",              tcu::Sampler::CLAMP_TO_EDGE                     },
2362                 { "repeat",                             tcu::Sampler::REPEAT_GL                         },
2363                 { "mirrored_repeat",    tcu::Sampler::MIRRORED_REPEAT_GL        }
2364         };
2365
2366         for (int gatherTypeI = 0; gatherTypeI < GATHERTYPE_LAST; gatherTypeI++)
2367         {
2368                 const GatherType                gatherType                      = (GatherType)gatherTypeI;
2369                 TestCaseGroup* const    gatherTypeGroup         = new TestCaseGroup(m_testCtx, gatherTypeName(gatherType), gatherTypeDescription(gatherType));
2370                 addChild(gatherTypeGroup);
2371
2372                 for (int offsetSizeI = 0; offsetSizeI < OFFSETSIZE_LAST; offsetSizeI++)
2373                 {
2374                         const OffsetSize offsetSize = (OffsetSize)offsetSizeI;
2375                         if ((gatherType == GATHERTYPE_BASIC) != (offsetSize == OFFSETSIZE_NONE))
2376                                 continue;
2377
2378                         if (gatherType == GATHERTYPE_OFFSETS && offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM) // \note offsets argument must be compile-time constant
2379                                 continue;
2380
2381                         TestCaseGroup* const offsetSizeGroup = offsetSize == OFFSETSIZE_NONE ?
2382                                                                                                         gatherTypeGroup :
2383                                                                                                         new TestCaseGroup(m_testCtx,
2384                                                                                                                                           offsetSize == OFFSETSIZE_MINIMUM_REQUIRED                             ? "min_required_offset"
2385                                                                                                                                           : offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM             ? "implementation_offset"
2386                                                                                                                                           : DE_NULL,
2387                                                                                                                                           offsetSize == OFFSETSIZE_MINIMUM_REQUIRED                             ? "Use offsets within Vulkan minimum required range"
2388                                                                                                                                           : offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM             ? "Use offsets within the implementation range"
2389                                                                                                                                           : DE_NULL);
2390
2391                         if (offsetSizeGroup != gatherTypeGroup)
2392                                 gatherTypeGroup->addChild(offsetSizeGroup);
2393
2394                         for (int textureTypeNdx = 0; textureTypeNdx < DE_LENGTH_OF_ARRAY(textureTypes); textureTypeNdx++)
2395                         {
2396                                 const TextureType textureType = textureTypes[textureTypeNdx].type;
2397
2398                                 if (textureType == TEXTURETYPE_CUBE && gatherType != GATHERTYPE_BASIC)
2399                                         continue;
2400
2401                                 TestCaseGroup* const textureTypeGroup = new TestCaseGroup(m_testCtx, textureTypes[textureTypeNdx].name, "");
2402                                 offsetSizeGroup->addChild(textureTypeGroup);
2403
2404                                 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
2405                                 {
2406                                         const tcu::TextureFormat&       format                  = formats[formatNdx].format;
2407                                         TestCaseGroup* const            formatGroup             = new TestCaseGroup(m_testCtx, formats[formatNdx].name, "");
2408                                         textureTypeGroup->addChild(formatGroup);
2409
2410                                         for (int noCornersI = 0; noCornersI <= ((textureType == TEXTURETYPE_CUBE)?1:0); noCornersI++)
2411                                         {
2412                                                 const bool                              noCorners               = noCornersI!= 0;
2413                                                 TestCaseGroup* const    cornersGroup    = noCorners
2414                                                                                                                                 ? new TestCaseGroup(m_testCtx, "no_corners", "Test case variants that don't sample around cube map corners")
2415                                                                                                                                 : formatGroup;
2416
2417                                                 if (formatGroup != cornersGroup)
2418                                                         formatGroup->addChild(cornersGroup);
2419
2420                                                 for (int textureSizeNdx = 0; textureSizeNdx < DE_LENGTH_OF_ARRAY(textureSizes); textureSizeNdx++)
2421                                                 {
2422                                                         const IVec3&                    textureSize                     = textureSizes[textureSizeNdx].size;
2423                                                         TestCaseGroup* const    textureSizeGroup        = new TestCaseGroup(m_testCtx, textureSizes[textureSizeNdx].name, "");
2424                                                         cornersGroup->addChild(textureSizeGroup);
2425
2426                                                         for (int compareModeI = 0; compareModeI < tcu::Sampler::COMPAREMODE_LAST; compareModeI++)
2427                                                         {
2428                                                                 const tcu::Sampler::CompareMode compareMode = (tcu::Sampler::CompareMode)compareModeI;
2429
2430                                                                 if ((compareMode != tcu::Sampler::COMPAREMODE_NONE) != isDepthFormat(format))
2431                                                                         continue;
2432
2433                                                                 if (compareMode != tcu::Sampler::COMPAREMODE_NONE &&
2434                                                                         compareMode != tcu::Sampler::COMPAREMODE_LESS &&
2435                                                                         compareMode != tcu::Sampler::COMPAREMODE_GREATER)
2436                                                                         continue;
2437
2438                                                                 TestCaseGroup* const compareModeGroup = compareMode == tcu::Sampler::COMPAREMODE_NONE ?
2439                                                                                                                                                         textureSizeGroup :
2440                                                                                                                                                         new TestCaseGroup(m_testCtx,
2441                                                                                                                                                                                           (string() + "compare_" + compareModeName(compareMode)).c_str(),
2442                                                                                                                                                                                           "");
2443                                                                 if (compareModeGroup != textureSizeGroup)
2444                                                                         textureSizeGroup->addChild(compareModeGroup);
2445
2446                                                                 for (int wrapCaseNdx = 0; wrapCaseNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapCaseNdx++)
2447                                                                 {
2448                                                                         const int                                               wrapSNdx        = wrapCaseNdx;
2449                                                                         const int                                               wrapTNdx        = (wrapCaseNdx + 1) % DE_LENGTH_OF_ARRAY(wrapModes);
2450                                                                         const tcu::Sampler::WrapMode    wrapS           = wrapModes[wrapSNdx].mode;
2451                                                                         const tcu::Sampler::WrapMode    wrapT           = wrapModes[wrapTNdx].mode;
2452
2453                                                                         const string caseName = string() + wrapModes[wrapSNdx].name + "_" + wrapModes[wrapTNdx].name;
2454
2455                                                                         compareModeGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, caseName.c_str(), "", gatherType, offsetSize, format, compareMode, wrapS, wrapT,
2456                                                                                                                                                                          MaybeTextureSwizzle::createNoneTextureSwizzle(), tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0, textureSize,
2457                                                                                                                                                                          noCorners ? GATHERCASE_DONT_SAMPLE_CUBE_CORNERS : 0));
2458                                                                         compareModeGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, "sparse_" + caseName, "", gatherType, offsetSize, format, compareMode, wrapS, wrapT,
2459                                                                                                                                                                          MaybeTextureSwizzle::createNoneTextureSwizzle(), tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0, textureSize,
2460                                                                                                                                                                          noCorners ? GATHERCASE_DONT_SAMPLE_CUBE_CORNERS : 0, ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE));
2461                                                                 }
2462                                                         }
2463                                                 }
2464                                         }
2465
2466                                         if (offsetSize != OFFSETSIZE_MINIMUM_REQUIRED || gatherType == GATHERTYPE_OFFSETS) // Don't test all features for both offset size types, as they should be rather orthogonal.
2467                                         {
2468                                                 if (!isDepthFormat(format))
2469                                                 {
2470                                                         TestCaseGroup* const swizzleGroup = new TestCaseGroup(m_testCtx, "texture_swizzle", "");
2471                                                         formatGroup->addChild(swizzleGroup);
2472
2473                                                         DE_STATIC_ASSERT(TEXTURESWIZZLECOMPONENT_R == 0);
2474                                                         for (int swizzleCaseNdx = 0; swizzleCaseNdx < TEXTURESWIZZLECOMPONENT_LAST; swizzleCaseNdx++)
2475                                                         {
2476                                                                 MaybeTextureSwizzle     swizzle = MaybeTextureSwizzle::createSomeTextureSwizzle();
2477                                                                 string                          caseName;
2478
2479                                                                 for (int i = 0; i < 4; i++)
2480                                                                 {
2481                                                                         swizzle.getSwizzle()[i] = (TextureSwizzleComponent)((swizzleCaseNdx + i) % (int)TEXTURESWIZZLECOMPONENT_LAST);
2482                                                                         caseName += (i > 0 ? "_" : "") + de::toLower(de::toString(swizzle.getSwizzle()[i]));
2483                                                                 }
2484
2485                                                                 swizzleGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, caseName.c_str(), "", gatherType, offsetSize, format,
2486                                                                                                                                                          tcu::Sampler::COMPAREMODE_NONE, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2487                                                                                                                                                          swizzle, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0, IVec3(64, 64, 3)));
2488                                                                 swizzleGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, "sparse_" + caseName, "", gatherType, offsetSize, format,
2489                                                                                                                                                          tcu::Sampler::COMPAREMODE_NONE, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2490                                                                                                                                                          swizzle, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0, IVec3(64, 64, 3), 0, ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE));
2491                                                         }
2492                                                 }
2493
2494                                                 {
2495                                                         TestCaseGroup* const filterModeGroup = new TestCaseGroup(m_testCtx, "filter_mode", "Test that filter modes have no effect");
2496                                                         formatGroup->addChild(filterModeGroup);
2497
2498                                                         const struct
2499                                                         {
2500                                                                 const char*                                     name;
2501                                                                 tcu::Sampler::FilterMode        filter;
2502                                                         } magFilters[] =
2503                                                         {
2504                                                                 { "linear",             tcu::Sampler::LINEAR    },
2505                                                                 { "nearest",    tcu::Sampler::NEAREST   }
2506                                                         };
2507
2508                                                         const struct
2509                                                         {
2510                                                                 const char*                                     name;
2511                                                                 tcu::Sampler::FilterMode        filter;
2512                                                         } minFilters[] =
2513                                                         {
2514                                                                 // \note Don't test NEAREST here, as it's covered by other cases.
2515                                                                 { "linear",                                             tcu::Sampler::LINEAR                                    },
2516                                                                 { "nearest_mipmap_nearest",             tcu::Sampler::NEAREST_MIPMAP_NEAREST    },
2517                                                                 { "nearest_mipmap_linear",              tcu::Sampler::NEAREST_MIPMAP_LINEAR             },
2518                                                                 { "linear_mipmap_nearest",              tcu::Sampler::LINEAR_MIPMAP_NEAREST             },
2519                                                                 { "linear_mipmap_linear",               tcu::Sampler::LINEAR_MIPMAP_LINEAR              },
2520                                                         };
2521
2522                                                         for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilters); minFilterNdx++)
2523                                                         for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilters); magFilterNdx++)
2524                                                         {
2525                                                                 const tcu::Sampler::FilterMode          minFilter               = minFilters[minFilterNdx].filter;
2526                                                                 const tcu::Sampler::FilterMode          magFilter               = magFilters[magFilterNdx].filter;
2527                                                                 const tcu::Sampler::CompareMode         compareMode             = isDepthFormat(format) ? tcu::Sampler::COMPAREMODE_LESS : tcu::Sampler::COMPAREMODE_NONE;
2528
2529                                                                 if ((isUnormFormatType(format.type) || isDepthFormat(format)) && magFilter == tcu::Sampler::NEAREST)
2530                                                                         continue; // Covered by other cases.
2531                                                                 if ((isUIntFormatType(format.type) || isSIntFormatType(format.type)) &&
2532                                                                         (magFilter != tcu::Sampler::NEAREST || minFilter != tcu::Sampler::NEAREST_MIPMAP_NEAREST))
2533                                                                         continue;
2534
2535                                                                 const string caseName = string() + "min_" + minFilters[minFilterNdx].name + "_mag_" + magFilters[magFilterNdx].name;
2536
2537                                                                 filterModeGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, caseName.c_str(), "", gatherType, offsetSize, format, compareMode,
2538                                                                                                                                                                 tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, MaybeTextureSwizzle::createNoneTextureSwizzle(),
2539                                                                                                                                                                 minFilter, magFilter, 0, IVec3(64, 64, 3)));
2540                                                                 filterModeGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, "sparse_" + caseName, "", gatherType, offsetSize, format, compareMode,
2541                                                                                                                                                                 tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, MaybeTextureSwizzle::createNoneTextureSwizzle(),
2542                                                                                                                                                                 minFilter, magFilter, 0, IVec3(64, 64, 3), 0, ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE));
2543                                                         }
2544                                                 }
2545
2546                                                 {
2547                                                         TestCaseGroup* const baseLevelGroup = new TestCaseGroup(m_testCtx, "base_level", "");
2548                                                         formatGroup->addChild(baseLevelGroup);
2549
2550                                                         for (int baseLevel = 1; baseLevel <= 2; baseLevel++)
2551                                                         {
2552                                                                 const string                                            caseName                = "level_" + de::toString(baseLevel);
2553                                                                 const tcu::Sampler::CompareMode         compareMode             = isDepthFormat(format) ? tcu::Sampler::COMPAREMODE_LESS : tcu::Sampler::COMPAREMODE_NONE;
2554                                                                 baseLevelGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, caseName.c_str(), "", gatherType, offsetSize, format,
2555                                                                                                                                                            compareMode, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2556                                                                                                                                                            MaybeTextureSwizzle::createNoneTextureSwizzle(), tcu::Sampler::NEAREST, tcu::Sampler::NEAREST,
2557                                                                                                                                                            baseLevel, IVec3(64, 64, 3)));
2558                                                                 baseLevelGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, "sparse_" + caseName, "", gatherType, offsetSize, format,
2559                                                                                                                                                            compareMode, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2560                                                                                                                                                            MaybeTextureSwizzle::createNoneTextureSwizzle(), tcu::Sampler::NEAREST, tcu::Sampler::NEAREST,
2561                                                                                                                                                            baseLevel, IVec3(64, 64, 3), 0, ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE));
2562                                                         }
2563                                                 }
2564                                         }
2565                                 }
2566                         }
2567                 }
2568         }
2569 }
2570
2571 } // anonymous
2572
2573 tcu::TestCaseGroup* createTextureGatherTests (tcu::TestContext& testCtx)
2574 {
2575         return new TextureGatherTests(testCtx);
2576 }
2577
2578 } // sr
2579 } // vkt