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