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
getBitsVec(const tcu::PixelFormat & format)86 inline tcu::IVec4 getBitsVec (const tcu::PixelFormat& format)
87 {
88 return tcu::IVec4(format.redBits, format.greenBits, format.blueBits, format.alphaBits);
89 }
90
getCompareMask(const tcu::PixelFormat & format)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
computeQuadTexCoord2D(std::vector<float> & dst,const tcu::Vec2 & bottomLeft,const tcu::Vec2 & topRight)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
computeQuadTexCoord2DArray(std::vector<float> & dst,int layerNdx,const tcu::Vec2 & bottomLeft,const tcu::Vec2 & topRight)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
computeQuadTexCoordCube(std::vector<float> & dst,tcu::CubeFace face,const tcu::Vec2 & bottomLeft,const tcu::Vec2 & topRight)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.
divRoundToZero(int a,int b)162 static inline int divRoundToZero (int a, int b)
163 {
164 return de::abs(a) / de::abs(b) * deSign32(a) * deSign32(b);
165 }
166
fillWithRandomColorTiles(const PixelBufferAccess & dst,const Vec4 & minVal,const Vec4 & maxVal,deUint32 seed)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
isDepthFormat(const tcu::TextureFormat & fmt)188 static inline bool isDepthFormat (const tcu::TextureFormat& fmt)
189 {
190 return fmt.order == tcu::TextureFormat::D || fmt.order == tcu::TextureFormat::DS;
191 }
192
isUnormFormatType(tcu::TextureFormat::ChannelType type)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
isSIntFormatType(tcu::TextureFormat::ChannelType type)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
isUIntFormatType(tcu::TextureFormat::ChannelType type)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
operator <<(std::ostream & stream,TextureSwizzleComponent comp)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
operator <<(std::ostream & stream,const MaybeTextureSwizzle & comp)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
createNoneTextureSwizzle(void)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
createSomeTextureSwizzle(void)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
isSome(void) const300 bool MaybeTextureSwizzle::isSome (void) const
301 {
302 return m_isSome;
303 }
304
isNone(void) const305 bool MaybeTextureSwizzle::isNone (void) const
306 {
307 return !m_isSome;
308 }
309
isIdentitySwizzle(void) const310 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
getSwizzle(void)319 tcu::Vector<TextureSwizzleComponent, 4>& MaybeTextureSwizzle::getSwizzle (void)
320 {
321 return m_swizzle;
322 }
323
getSwizzle(void) const324 const tcu::Vector<TextureSwizzleComponent, 4>& MaybeTextureSwizzle::getSwizzle (void) const
325 {
326 return m_swizzle;
327 }
328
MaybeTextureSwizzle(void)329 MaybeTextureSwizzle::MaybeTextureSwizzle (void)
330 : m_swizzle (TEXTURESWIZZLECOMPONENT_LAST, TEXTURESWIZZLECOMPONENT_LAST, TEXTURESWIZZLECOMPONENT_LAST, TEXTURESWIZZLECOMPONENT_LAST)
331 , m_isSome (false)
332 {
333 }
334
getTextureSwizzleComponent(TextureSwizzleComponent c)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>
swizzleColorChannel(const tcu::Vector<T,4> & src,TextureSwizzleComponent swizzle)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>
swizzleColor(const tcu::Vector<T,4> & src,const MaybeTextureSwizzle & swizzle)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>
swizzlePixels(const PixelBufferAccess & dst,const ConstPixelBufferAccess & src,const MaybeTextureSwizzle & swizzle)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
swizzlePixels(const PixelBufferAccess & dst,const ConstPixelBufferAccess & src,const MaybeTextureSwizzle & swizzle)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
swizzleTexture(tcu::Texture2D & dst,const tcu::Texture2D & src,const MaybeTextureSwizzle & swizzle)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
swizzleTexture(tcu::Texture2DArray & dst,const tcu::Texture2DArray & src,const MaybeTextureSwizzle & swizzle)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
swizzleTexture(tcu::TextureCube & dst,const tcu::TextureCube & src,const MaybeTextureSwizzle & swizzle)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
getOneLevelSubView(const tcu::Texture2DView & view,int level)444 static tcu::Texture2DView getOneLevelSubView (const tcu::Texture2DView& view, int level)
445 {
446 return tcu::Texture2DView(1, view.getLevels() + level);
447 }
448
getOneLevelSubView(const tcu::Texture2DArrayView & view,int level)449 static tcu::Texture2DArrayView getOneLevelSubView (const tcu::Texture2DArrayView& view, int level)
450 {
451 return tcu::Texture2DArrayView(1, view.getLevels() + level);
452 }
453
getOneLevelSubView(const tcu::TextureCubeView & view,int level)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;
~PixelOffsets(void)468 virtual ~PixelOffsets (void) {}
469 };
470
471 class MultiplePixelOffsets : public PixelOffsets
472 {
473 public:
MultiplePixelOffsets(const IVec2 & a,const IVec2 & b,const IVec2 & c,const IVec2 & d)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
operator ()(const IVec2 &,IVec2 (& dst)[4]) const485 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:
SinglePixelOffsets(const IVec2 & offset)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:
DynamicSinglePixelOffsets(const IVec2 & offsetRange)510 DynamicSinglePixelOffsets (const IVec2& offsetRange) : m_offsetRange(offsetRange) {}
511
operator ()(const IVec2 & pixCoord,IVec2 (& dst)[4]) const512 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>
triQuadInterpolate(const T (& values)[4],float xFactor,float yFactor)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>
computeTexCoordVecs(const vector<float> & texCoords,tcu::Vector<float,N> (& dst)[4])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().
isZeroOffsetOffsets(const IVec2 (& offsets)[4])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>
gatherOffsets(const tcu::Texture2DView & texture,const tcu::Sampler & sampler,const Vec2 & coord,int componentNdx,const IVec2 (& offsets)[4])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>
gatherOffsets(const tcu::Texture2DArrayView & texture,const tcu::Sampler & sampler,const Vec3 & coord,int componentNdx,const IVec2 (& offsets)[4])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>
gatherOffsets(const tcu::TextureCubeView & texture,const tcu::Sampler & sampler,const Vec3 & coord,int componentNdx,const IVec2 (& offsets)[4])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
gatherOffsetsCompare(const tcu::Texture2DView & texture,const tcu::Sampler & sampler,float refZ,const Vec2 & coord,const IVec2 (& offsets)[4])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
gatherOffsetsCompare(const tcu::Texture2DArrayView & texture,const tcu::Sampler & sampler,float refZ,const Vec3 & coord,const IVec2 (& offsets)[4])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
gatherOffsetsCompare(const tcu::TextureCubeView & texture,const tcu::Sampler & sampler,float refZ,const Vec3 & coord,const IVec2 (& offsets)[4])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>
isGatherOffsetsResultValid(const tcu::TextureCubeView & texture,const tcu::Sampler & sampler,const PrecType & prec,const Vec3 & coord,int componentNdx,const IVec2 (& offsets)[4],const tcu::Vector<ColorScalarT,4> & result)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
isGatherOffsetsCompareResultValid(const tcu::TextureCubeView & texture,const tcu::Sampler & sampler,const tcu::TexComparePrecision & prec,const Vec3 & coord,const IVec2 (& offsets)[4],float cmpReference,const Vec4 & result)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>
verifyGatherOffsets(TestLog & log,const ConstPixelBufferAccess & result,const TexViewT & texture,const TexCoordT (& texCoords)[4],const tcu::Sampler & sampler,const PrecType & lookupPrec,int componentNdx,const PixelOffsets & getPixelOffsets)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:
PixelCompareRefZDefault(const IVec2 & renderSize)685 PixelCompareRefZDefault (const IVec2& renderSize) : m_renderSize(renderSize) {}
686
operator ()(const IVec2 & pixCoord) const687 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>
verifyGatherOffsetsCompare(TestLog & log,const ConstPixelBufferAccess & result,const TexViewT & texture,const TexCoordT (& texCoords)[4],const tcu::Sampler & sampler,const tcu::TexComparePrecision & compPrec,const PixelCompareRefZ & getPixelRefZ,const PixelOffsets & getPixelOffsets)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
gatherTypeName(GatherType type)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
gatherTypeDescription(GatherType type)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
requireGpuShader5(GatherType gatherType,OffsetSize offsetSize)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
GatherArgsvkt::sr::__anonf1da81390111::GatherArgs812 GatherArgs (void)
813 : componentNdx(-1)
814 {
815 std::fill(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), IVec2());
816 }
817
GatherArgsvkt::sr::__anonf1da81390111::GatherArgs818 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
makePixelOffsetsFunctor(GatherType gatherType,const GatherArgs & gatherArgs,const IVec2 & offsetRange)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
getSamplerType(TextureType textureType,const tcu::TextureFormat & format)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
getSamplerGatherResultType(glu::DataType samplerType)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
getNumTextureSamplingDimensions(TextureType type)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
generateBasic2DCaseIterations(GatherType gatherType,const tcu::TextureFormat & textureFormat,const IVec2 & offsetRange)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
GatherCaseBaseParamsvkt::sr::__anonf1da81390111::GatherCaseBaseParams1006 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
GatherCaseBaseParamsvkt::sr::__anonf1da81390111::GatherCaseBaseParams1034 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
getOffsetRange(const OffsetSize offsetSize,const vk::VkPhysicalDeviceLimits & deviceLimits)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
getOffsetRange(const OffsetSize offsetSize)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
TextureGatherInstance(Context & context,const GatherCaseBaseParams & baseParams)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
~TextureGatherInstance(void)1157 TextureGatherInstance::~TextureGatherInstance (void)
1158 {
1159 }
1160
init(void)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
setupDefaultInputs(void)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
iterate(void)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
setupUniforms(const tcu::Vec4 &)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>
verify(const ConstPixelBufferAccess & rendered,const TexViewT & texture,const TexCoordT (& texCoords)[4],const GatherArgs & gatherArgs) const1333 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
genVertexShaderSource(bool requireGpuShader5,int numTexCoordComponents,bool useNormalizedCoordInput)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
genFragmentShaderSource(bool requireGpuShader5,int numTexCoordComponents,glu::DataType samplerType,const string & funcCall,bool useNormalizedCoordInput,bool usePixCoord,OffsetSize offsetSize,const ImageBackingMode sparseCase)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
genGatherFuncCall(GatherType gatherType,const tcu::TextureFormat & textureFormat,const GatherArgs & gatherArgs,const string & refZExpr,const IVec2 & offsetRange,int indentationDepth,OffsetSize offsetSize,const ImageBackingMode sparseCase)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
genGatherPrograms(vk::SourceCollections & programCollection,const GatherCaseBaseParams & baseParams,const vector<GatherArgs> & iterations)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:
getNumIterations(void) const1669 virtual int getNumIterations (void) const { return (int)m_iterations.size(); }
getGatherArgs(int iterationNdx) const1670 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
TextureGather2DInstance(Context & context,const GatherCaseBaseParams & baseParams,const IVec2 & textureSize,const vector<GatherArgs> & iterations)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
~TextureGather2DInstance(void)1695 TextureGather2DInstance::~TextureGather2DInstance (void)
1696 {
1697 }
1698
computeQuadTexCoord(int) const1699 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
createTexture(void)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
verify(int iterationNdx,const ConstPixelBufferAccess & rendered) const1735 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
TextureGather2DCase(tcu::TestContext & testCtx,const string & name,const string & description,const GatherType gatherType,const OffsetSize offsetSize,const tcu::TextureFormat textureFormat,const tcu::Sampler::CompareMode shadowCompareMode,const tcu::Sampler::WrapMode wrapS,const tcu::Sampler::WrapMode wrapT,const MaybeTextureSwizzle & textureSwizzle,const tcu::Sampler::FilterMode minFilter,const tcu::Sampler::FilterMode magFilter,const int baseLevel,const deUint32 flags,const IVec2 & textureSize,const ImageBackingMode sparseCase)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
~TextureGather2DCase(void)1793 TextureGather2DCase::~TextureGather2DCase (void)
1794 {
1795 }
1796
initPrograms(vk::SourceCollections & dst) const1797 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
createInstance(Context & context) const1806 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
operator GatherArgsvkt::sr::__anonf1da81390111::Gather2DArrayArgs1822 operator GatherArgs() const { return gatherArgs; }
1823 };
1824
generate2DArrayCaseIterations(GatherType gatherType,const tcu::TextureFormat & textureFormat,const IVec2 & offsetRange,const IVec3 & textureSize)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:
getNumIterations(void) const1875 virtual int getNumIterations (void) const { return (int)m_iterations.size(); }
getGatherArgs(int iterationNdx) const1876 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
TextureGather2DArrayInstance(Context & context,const GatherCaseBaseParams & baseParams,const IVec3 & textureSize,const vector<Gather2DArrayArgs> & iterations)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
~TextureGather2DArrayInstance(void)1901 TextureGather2DArrayInstance::~TextureGather2DArrayInstance (void)
1902 {
1903 }
1904
computeQuadTexCoord(int iterationNdx) const1905 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
createTexture(void)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
verify(int iterationNdx,const ConstPixelBufferAccess & rendered) const1947 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
TextureGather2DArrayCase(tcu::TestContext & testCtx,const string & name,const string & description,const GatherType gatherType,const OffsetSize offsetSize,const tcu::TextureFormat textureFormat,const tcu::Sampler::CompareMode shadowCompareMode,const tcu::Sampler::WrapMode wrapS,const tcu::Sampler::WrapMode wrapT,const MaybeTextureSwizzle & textureSwizzle,const tcu::Sampler::FilterMode minFilter,const tcu::Sampler::FilterMode magFilter,const int baseLevel,const deUint32 flags,const IVec3 & textureSize,const ImageBackingMode sparseCase)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
~TextureGather2DArrayCase(void)2005 TextureGather2DArrayCase::~TextureGather2DArrayCase (void)
2006 {
2007 }
2008
initPrograms(vk::SourceCollections & dst) const2009 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
createInstance(Context & context) const2019 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
operator GatherArgsvkt::sr::__anonf1da81390111::GatherCubeArgs2036 operator GatherArgs() const { return gatherArgs; }
2037 };
2038
generateCubeCaseIterations(GatherType gatherType,const tcu::TextureFormat & textureFormat,const IVec2 & offsetRange)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:
getNumIterations(void) const2087 virtual int getNumIterations (void) const { return (int)m_iterations.size(); }
getGatherArgs(int iterationNdx) const2088 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
TextureGatherCubeInstance(Context & context,const GatherCaseBaseParams & baseParams,const int textureSize,const vector<GatherCubeArgs> & iterations)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
~TextureGatherCubeInstance(void)2113 TextureGatherCubeInstance::~TextureGatherCubeInstance (void)
2114 {
2115 }
2116
computeQuadTexCoord(int iterationNdx) const2117 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
createTexture(void)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
verify(int iterationNdx,const ConstPixelBufferAccess & rendered) const2166 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
TextureGatherCubeCase(tcu::TestContext & testCtx,const string & name,const string & description,const tcu::TextureFormat textureFormat,const tcu::Sampler::CompareMode shadowCompareMode,const tcu::Sampler::WrapMode wrapS,const tcu::Sampler::WrapMode wrapT,const MaybeTextureSwizzle & textureSwizzle,const tcu::Sampler::FilterMode minFilter,const tcu::Sampler::FilterMode magFilter,const int baseLevel,const deUint32 flags,const int textureSize,const ImageBackingMode sparseCase)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
~TextureGatherCubeCase(void)2221 TextureGatherCubeCase::~TextureGatherCubeCase (void)
2222 {
2223 }
2224
initPrograms(vk::SourceCollections & dst) const2225 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
createInstance(Context & context) const2234 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
TextureGatherTests(tcu::TestContext & context)2255 TextureGatherTests::TextureGatherTests (tcu::TestContext& context)
2256 : TestCaseGroup(context, "texture_gather", "textureGather* tests")
2257 {
2258 }
2259
~TextureGatherTests(void)2260 TextureGatherTests::~TextureGatherTests (void)
2261 {
2262 }
2263
makeTextureGatherCase(TextureType textureType,tcu::TestContext & testCtx,const string & name,const string & description,GatherType gatherType,OffsetSize offsetSize,tcu::TextureFormat textureFormat,tcu::Sampler::CompareMode shadowCompareMode,tcu::Sampler::WrapMode wrapS,tcu::Sampler::WrapMode wrapT,const MaybeTextureSwizzle & texSwizzle,tcu::Sampler::FilterMode minFilter,tcu::Sampler::FilterMode magFilter,int baseLevel,const IVec3 & textureSize,deUint32 flags=0,const ImageBackingMode sparseCase=ShaderRenderCaseInstance::IMAGE_BACKING_MODE_REGULAR)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
compareModeName(tcu::Sampler::CompareMode mode)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
init(void)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
createTextureGatherTests(tcu::TestContext & testCtx)2573 tcu::TestCaseGroup* createTextureGatherTests (tcu::TestContext& testCtx)
2574 {
2575 return new TextureGatherTests(testCtx);
2576 }
2577
2578 } // sr
2579 } // vkt
2580