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
gatherTypeDescription(GatherType type)792 static inline const char* gatherTypeDescription (GatherType type)
793 {
794 switch (type)
795 {
796 case GATHERTYPE_BASIC: return "textureGather";
797 case GATHERTYPE_OFFSET: return "textureGatherOffset";
798 case GATHERTYPE_OFFSET_DYNAMIC: return "textureGatherOffset with dynamic offsets";
799 case GATHERTYPE_OFFSETS: return "textureGatherOffsets";
800 default: DE_ASSERT(false); return DE_NULL;
801 }
802 }
803
requireGpuShader5(GatherType gatherType,OffsetSize offsetSize)804 static inline bool requireGpuShader5 (GatherType gatherType, OffsetSize offsetSize)
805 {
806 return gatherType == GATHERTYPE_OFFSET_DYNAMIC || gatherType == GATHERTYPE_OFFSETS
807 || offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM; // \note Implementation limits are not available while generating the shaders, they are passed dynamically at runtime
808 }
809
810 struct GatherArgs
811 {
812 int componentNdx; // If negative, implicit component index 0 is used (i.e. the parameter is not given).
813 IVec2 offsets[4]; // \note Unless GATHERTYPE_OFFSETS is used, only offsets[0] is relevant; also, for GATHERTYPE_OFFSET_DYNAMIC, none are relevant.
814
GatherArgsvkt::sr::__anonac2a49bc0111::GatherArgs815 GatherArgs (void)
816 : componentNdx(-1)
817 {
818 std::fill(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), IVec2());
819 }
820
GatherArgsvkt::sr::__anonac2a49bc0111::GatherArgs821 GatherArgs (int comp,
822 const IVec2& off0 = IVec2(),
823 const IVec2& off1 = IVec2(),
824 const IVec2& off2 = IVec2(),
825 const IVec2& off3 = IVec2())
826 : componentNdx(comp)
827 {
828 offsets[0] = off0;
829 offsets[1] = off1;
830 offsets[2] = off2;
831 offsets[3] = off3;
832 }
833 };
834
makePixelOffsetsFunctor(GatherType gatherType,const GatherArgs & gatherArgs,const IVec2 & offsetRange)835 static MovePtr<PixelOffsets> makePixelOffsetsFunctor (GatherType gatherType, const GatherArgs& gatherArgs, const IVec2& offsetRange)
836 {
837 if (gatherType == GATHERTYPE_BASIC || gatherType == GATHERTYPE_OFFSET)
838 {
839 const IVec2 offset = gatherType == GATHERTYPE_BASIC ? IVec2(0) : gatherArgs.offsets[0];
840 return MovePtr<PixelOffsets>(new SinglePixelOffsets(offset));
841 }
842 else if (gatherType == GATHERTYPE_OFFSET_DYNAMIC)
843 {
844 return MovePtr<PixelOffsets>(new DynamicSinglePixelOffsets(offsetRange));
845 }
846 else if (gatherType == GATHERTYPE_OFFSETS)
847 return MovePtr<PixelOffsets>(new MultiplePixelOffsets(gatherArgs.offsets[0],
848 gatherArgs.offsets[1],
849 gatherArgs.offsets[2],
850 gatherArgs.offsets[3]));
851 else
852 {
853 DE_ASSERT(false);
854 return MovePtr<PixelOffsets>(DE_NULL);
855 }
856 }
857
getSamplerType(TextureType textureType,const tcu::TextureFormat & format)858 static inline glu::DataType getSamplerType (TextureType textureType, const tcu::TextureFormat& format)
859 {
860 if (isDepthFormat(format))
861 {
862 switch (textureType)
863 {
864 case TEXTURETYPE_2D: return glu::TYPE_SAMPLER_2D_SHADOW;
865 case TEXTURETYPE_2D_ARRAY: return glu::TYPE_SAMPLER_2D_ARRAY_SHADOW;
866 case TEXTURETYPE_CUBE: return glu::TYPE_SAMPLER_CUBE_SHADOW;
867 default: DE_ASSERT(false); return glu::TYPE_LAST;
868 }
869 }
870 else
871 {
872 switch (textureType)
873 {
874 case TEXTURETYPE_2D: return glu::getSampler2DType(format);
875 case TEXTURETYPE_2D_ARRAY: return glu::getSampler2DArrayType(format);
876 case TEXTURETYPE_CUBE: return glu::getSamplerCubeType(format);
877 default: DE_ASSERT(false); return glu::TYPE_LAST;
878 }
879 }
880 }
881
getSamplerGatherResultType(glu::DataType samplerType)882 static inline glu::DataType getSamplerGatherResultType (glu::DataType samplerType)
883 {
884 switch (samplerType)
885 {
886 case glu::TYPE_SAMPLER_2D_SHADOW:
887 case glu::TYPE_SAMPLER_2D_ARRAY_SHADOW:
888 case glu::TYPE_SAMPLER_CUBE_SHADOW:
889 case glu::TYPE_SAMPLER_2D:
890 case glu::TYPE_SAMPLER_2D_ARRAY:
891 case glu::TYPE_SAMPLER_CUBE:
892 return glu::TYPE_FLOAT_VEC4;
893
894 case glu::TYPE_INT_SAMPLER_2D:
895 case glu::TYPE_INT_SAMPLER_2D_ARRAY:
896 case glu::TYPE_INT_SAMPLER_CUBE:
897 return glu::TYPE_INT_VEC4;
898
899 case glu::TYPE_UINT_SAMPLER_2D:
900 case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
901 case glu::TYPE_UINT_SAMPLER_CUBE:
902 return glu::TYPE_UINT_VEC4;
903
904 default:
905 DE_ASSERT(false);
906 return glu::TYPE_LAST;
907 }
908 }
909
getNumTextureSamplingDimensions(TextureType type)910 static inline int getNumTextureSamplingDimensions (TextureType type)
911 {
912 switch (type)
913 {
914 case TEXTURETYPE_2D: return 2;
915 case TEXTURETYPE_2D_ARRAY: return 3;
916 case TEXTURETYPE_CUBE: return 3;
917 default: DE_ASSERT(false); return -1;
918 }
919 }
920
921 enum class LevelMode
922 {
923 NORMAL = 0,
924 AMD_BIAS,
925 AMD_LOD,
926 };
927
generateBasic2DCaseIterations(GatherType gatherType,LevelMode levelMode,const tcu::TextureFormat & textureFormat,const IVec2 & offsetRange)928 vector<GatherArgs> generateBasic2DCaseIterations (GatherType gatherType, LevelMode levelMode, const tcu::TextureFormat& textureFormat, const IVec2& offsetRange)
929 {
930 const int numComponentCases = isDepthFormat(textureFormat) ? 1 : 4+1; // \note For non-depth textures, test explicit components 0 to 3 and implicit component 0.
931 const bool skipImplicitCase = (levelMode == LevelMode::AMD_BIAS);
932 vector<GatherArgs> result;
933
934 for (int componentCaseNdx = (skipImplicitCase ? 1 : 0); componentCaseNdx < numComponentCases; componentCaseNdx++)
935 {
936 const int componentNdx = componentCaseNdx - 1;
937
938 switch (gatherType)
939 {
940 case GATHERTYPE_BASIC:
941 result.push_back(GatherArgs(componentNdx));
942 break;
943
944 case GATHERTYPE_OFFSET:
945 {
946 const int min = offsetRange.x();
947 const int max = offsetRange.y();
948 const int hmin = divRoundToZero(min, 2);
949 const int hmax = divRoundToZero(max, 2);
950
951 result.push_back(GatherArgs(componentNdx, IVec2(min, max)));
952
953 if (componentCaseNdx == 0) // Don't test all offsets variants for all color components (they should be pretty orthogonal).
954 {
955 result.push_back(GatherArgs(componentNdx, IVec2(min, min)));
956 result.push_back(GatherArgs(componentNdx, IVec2(max, min)));
957 result.push_back(GatherArgs(componentNdx, IVec2(max, max)));
958
959 result.push_back(GatherArgs(componentNdx, IVec2(0, hmax)));
960 result.push_back(GatherArgs(componentNdx, IVec2(hmin, 0)));
961 result.push_back(GatherArgs(componentNdx, IVec2(0, 0)));
962 }
963
964 break;
965 }
966
967 case GATHERTYPE_OFFSET_DYNAMIC:
968 result.push_back(GatherArgs(componentNdx));
969 break;
970
971 case GATHERTYPE_OFFSETS:
972 {
973 const int min = offsetRange.x();
974 const int max = offsetRange.y();
975 const int hmin = divRoundToZero(min, 2);
976 const int hmax = divRoundToZero(max, 2);
977
978 result.push_back(GatherArgs(componentNdx,
979 IVec2(min, min),
980 IVec2(min, max),
981 IVec2(max, min),
982 IVec2(max, max)));
983
984 if (componentCaseNdx == 0) // Don't test all offsets variants for all color components (they should be pretty orthogonal).
985 result.push_back(GatherArgs(componentNdx,
986 IVec2(min, hmax),
987 IVec2(hmin, max),
988 IVec2(0, hmax),
989 IVec2(hmax, 0)));
990 break;
991 }
992
993 default:
994 DE_ASSERT(false);
995 }
996 }
997
998 return result;
999 }
1000
1001 struct GatherCaseBaseParams
1002 {
1003 GatherType gatherType;
1004 OffsetSize offsetSize;
1005 tcu::TextureFormat textureFormat;
1006 tcu::Sampler::CompareMode shadowCompareMode;
1007 tcu::Sampler::WrapMode wrapS;
1008 tcu::Sampler::WrapMode wrapT;
1009 MaybeTextureSwizzle textureSwizzle;
1010 tcu::Sampler::FilterMode minFilter;
1011 tcu::Sampler::FilterMode magFilter;
1012 LevelMode levelMode;
1013 int baseLevel;
1014 deUint32 flags;
1015 TextureType textureType;
1016 ImageBackingMode sparseCase;
1017
GatherCaseBaseParamsvkt::sr::__anonac2a49bc0111::GatherCaseBaseParams1018 GatherCaseBaseParams (const TextureType textureType_,
1019 const GatherType gatherType_,
1020 const OffsetSize offsetSize_,
1021 const tcu::TextureFormat textureFormat_,
1022 const tcu::Sampler::CompareMode shadowCompareMode_,
1023 const tcu::Sampler::WrapMode wrapS_,
1024 const tcu::Sampler::WrapMode wrapT_,
1025 const MaybeTextureSwizzle& textureSwizzle_,
1026 const tcu::Sampler::FilterMode minFilter_,
1027 const tcu::Sampler::FilterMode magFilter_,
1028 const LevelMode levelMode_,
1029 const int baseLevel_,
1030 const deUint32 flags_,
1031 const ImageBackingMode sparseCase_)
1032 : gatherType (gatherType_)
1033 , offsetSize (offsetSize_)
1034 , textureFormat (textureFormat_)
1035 , shadowCompareMode (shadowCompareMode_)
1036 , wrapS (wrapS_)
1037 , wrapT (wrapT_)
1038 , textureSwizzle (textureSwizzle_)
1039 , minFilter (minFilter_)
1040 , magFilter (magFilter_)
1041 , levelMode (levelMode_)
1042 , baseLevel (baseLevel_)
1043 , flags (flags_)
1044 , textureType (textureType_)
1045 , sparseCase (sparseCase_)
1046 {}
1047
GatherCaseBaseParamsvkt::sr::__anonac2a49bc0111::GatherCaseBaseParams1048 GatherCaseBaseParams (void)
1049 : gatherType (GATHERTYPE_LAST)
1050 , offsetSize (OFFSETSIZE_LAST)
1051 , textureFormat ()
1052 , shadowCompareMode (tcu::Sampler::COMPAREMODE_LAST)
1053 , wrapS (tcu::Sampler::WRAPMODE_LAST)
1054 , wrapT (tcu::Sampler::WRAPMODE_LAST)
1055 , textureSwizzle (MaybeTextureSwizzle::createNoneTextureSwizzle())
1056 , minFilter (tcu::Sampler::FILTERMODE_LAST)
1057 , magFilter (tcu::Sampler::FILTERMODE_LAST)
1058 , levelMode (LevelMode::NORMAL)
1059 , baseLevel (0)
1060 , flags (0)
1061 , textureType (TEXTURETYPE_LAST)
1062 , sparseCase (ShaderRenderCaseInstance::IMAGE_BACKING_MODE_REGULAR)
1063 {}
1064 };
1065
checkMutableComparisonSamplersSupport(Context & context,const GatherCaseBaseParams & m_baseParams)1066 static void checkMutableComparisonSamplersSupport(Context& context, const GatherCaseBaseParams& m_baseParams)
1067 {
1068 // when compare mode is not none then ShaderRenderCaseInstance::createSamplerUniform
1069 // uses mapSampler utill from vkImageUtil that sets compareEnable to true
1070 // for portability this needs to be under feature flag
1071 #ifndef CTS_USES_VULKANSC
1072 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
1073 !context.getPortabilitySubsetFeatures().mutableComparisonSamplers &&
1074 (m_baseParams.shadowCompareMode != tcu::Sampler::COMPAREMODE_NONE))
1075 {
1076 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: mutableComparisonSamplers are not supported by this implementation");
1077 }
1078 #else
1079 DE_UNREF(context);
1080 DE_UNREF(m_baseParams);
1081 #endif // CTS_USES_VULKANSC
1082 }
1083
getOffsetRange(const OffsetSize offsetSize,const vk::VkPhysicalDeviceLimits & deviceLimits)1084 IVec2 getOffsetRange (const OffsetSize offsetSize, const vk::VkPhysicalDeviceLimits& deviceLimits)
1085 {
1086 switch (offsetSize)
1087 {
1088 case OFFSETSIZE_NONE:
1089 return IVec2(0);
1090
1091 case OFFSETSIZE_MINIMUM_REQUIRED:
1092 // \note Defined by spec.
1093 return IVec2(SPEC_MAX_MIN_OFFSET,
1094 SPEC_MIN_MAX_OFFSET);
1095
1096 case OFFSETSIZE_IMPLEMENTATION_MAXIMUM:
1097 return IVec2(deviceLimits.minTexelGatherOffset, deviceLimits.maxTexelGatherOffset);
1098
1099 default:
1100 DE_ASSERT(false);
1101 return IVec2(-1);
1102 }
1103 }
1104
getOffsetRange(const OffsetSize offsetSize)1105 IVec2 getOffsetRange (const OffsetSize offsetSize)
1106 {
1107 switch (offsetSize)
1108 {
1109 case OFFSETSIZE_NONE:
1110 return IVec2(0);
1111
1112 case OFFSETSIZE_MINIMUM_REQUIRED:
1113 // \note Defined by spec.
1114 return IVec2(SPEC_MAX_MIN_OFFSET,
1115 SPEC_MIN_MAX_OFFSET);
1116
1117 case OFFSETSIZE_IMPLEMENTATION_MAXIMUM:
1118 DE_FATAL("Not known");
1119 return IVec2(-1);
1120
1121 default:
1122 DE_ASSERT(false);
1123 return IVec2(-1);
1124 }
1125 }
1126
1127 class TextureGatherInstance : public ShaderRenderCaseInstance
1128 {
1129 public:
1130 TextureGatherInstance (Context& context,
1131 const GatherCaseBaseParams& baseParams);
1132 virtual ~TextureGatherInstance (void);
1133
1134 virtual tcu::TestStatus iterate (void);
1135
1136 protected:
1137 void init (void);
1138
1139 virtual int getNumIterations (void) const = 0;
1140 virtual GatherArgs getGatherArgs (int iterationNdx) const = 0;
1141
1142 virtual void setupDefaultInputs (void);
1143 virtual void setupUniforms (const tcu::Vec4&);
1144
1145 template <typename TexViewT, typename TexCoordT>
1146 bool verify (const ConstPixelBufferAccess& rendered,
1147 const TexViewT& texture,
1148 const TexCoordT (&bottomLeft)[4],
1149 const GatherArgs& gatherArgs) const;
1150
1151 virtual TextureBindingSp createTexture (void) = 0;
1152 virtual vector<float> computeQuadTexCoord (int iterationNdx) const = 0;
1153 virtual bool verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const = 0;
1154
1155 protected:
1156 static const IVec2 RENDER_SIZE;
1157
1158 const GatherCaseBaseParams m_baseParams;
1159
1160 private:
1161 const tcu::TextureFormat m_colorBufferFormat;
1162 int m_currentIteration;
1163 };
1164
1165 const IVec2 TextureGatherInstance::RENDER_SIZE = IVec2(64, 64);
1166
TextureGatherInstance(Context & context,const GatherCaseBaseParams & baseParams)1167 TextureGatherInstance::TextureGatherInstance (Context& context,
1168 const GatherCaseBaseParams& baseParams)
1169 : ShaderRenderCaseInstance (context, false, DE_NULL, DE_NULL, DE_NULL, baseParams.sparseCase)
1170 , m_baseParams (baseParams)
1171 , m_colorBufferFormat (tcu::TextureFormat(tcu::TextureFormat::RGBA,
1172 isDepthFormat(baseParams.textureFormat) ? tcu::TextureFormat::UNORM_INT8 : baseParams.textureFormat.type))
1173 , m_currentIteration (0)
1174 {
1175 DE_ASSERT((m_baseParams.gatherType == GATHERTYPE_BASIC) == (m_baseParams.offsetSize == OFFSETSIZE_NONE));
1176 DE_ASSERT((m_baseParams.shadowCompareMode != tcu::Sampler::COMPAREMODE_NONE) == isDepthFormat(m_baseParams.textureFormat));
1177 DE_ASSERT(isUnormFormatType(m_colorBufferFormat.type) ||
1178 m_colorBufferFormat.type == tcu::TextureFormat::UNSIGNED_INT8 ||
1179 m_colorBufferFormat.type == tcu::TextureFormat::UNSIGNED_INT16 ||
1180 m_colorBufferFormat.type == tcu::TextureFormat::SIGNED_INT8 ||
1181 m_colorBufferFormat.type == tcu::TextureFormat::SIGNED_INT16);
1182 DE_ASSERT(glu::isGLInternalColorFormatFilterable(glu::getInternalFormat(m_colorBufferFormat)) ||
1183 (m_baseParams.magFilter == tcu::Sampler::NEAREST && (m_baseParams.minFilter == tcu::Sampler::NEAREST || m_baseParams.minFilter == tcu::Sampler::NEAREST_MIPMAP_NEAREST)));
1184 DE_ASSERT(m_baseParams.textureType == TEXTURETYPE_CUBE || !(m_baseParams.flags & GATHERCASE_DONT_SAMPLE_CUBE_CORNERS));
1185
1186 m_renderSize = RENDER_SIZE.asUint();
1187 m_colorFormat = vk::mapTextureFormat(m_colorBufferFormat);
1188
1189 #ifdef CTS_USES_VULKANSC
1190 const VkDevice vkDevice = getDevice();
1191 const DeviceInterface& vk = getDeviceInterface();
1192 const deUint32 queueFamilyIndex = getUniversalQueueFamilyIndex();
1193 m_externalCommandPool = de::SharedPtr<Unique<VkCommandPool>>(new vk::Unique<VkCommandPool>(createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex)));
1194 #endif // CTS_USES_VULKANSC
1195 }
1196
~TextureGatherInstance(void)1197 TextureGatherInstance::~TextureGatherInstance (void)
1198 {
1199 }
1200
init(void)1201 void TextureGatherInstance::init (void)
1202 {
1203 TestLog& log = m_context.getTestContext().getLog();
1204 TextureBindingSp textureBinding;
1205 TextureBinding::Parameters textureParams;
1206
1207 // Check prerequisites.
1208 if (requireGpuShader5(m_baseParams.gatherType, m_baseParams.offsetSize))
1209 {
1210 const vk::VkPhysicalDeviceFeatures& deviceFeatures = m_context.getDeviceFeatures();
1211 if (!deviceFeatures.shaderImageGatherExtended)
1212 TCU_THROW(NotSupportedError, "Extended set of image gather instructions are not supported");
1213 }
1214
1215 // Check general extension support.
1216 if (m_baseParams.levelMode != LevelMode::NORMAL)
1217 {
1218 m_context.requireDeviceFunctionality("VK_AMD_texture_gather_bias_lod");
1219 }
1220
1221 // Log and check implementation offset limits, if appropriate.
1222 if (m_baseParams.offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
1223 {
1224 const IVec2 offsetRange = getOffsetRange(m_baseParams.offsetSize, m_context.getDeviceProperties().limits);
1225 log << TestLog::Integer("ImplementationMinTextureGatherOffset", "Implementation's value for minTexelGatherOffset", "", QP_KEY_TAG_NONE, offsetRange[0])
1226 << TestLog::Integer("ImplementationMaxTextureGatherOffset", "Implementation's value for maxTexelGatherOffset", "", QP_KEY_TAG_NONE, offsetRange[1]);
1227 TCU_CHECK_MSG(offsetRange[0] <= SPEC_MAX_MIN_OFFSET, ("minTexelGatherOffset must be at most " + de::toString((int)SPEC_MAX_MIN_OFFSET)).c_str());
1228 TCU_CHECK_MSG(offsetRange[1] >= SPEC_MIN_MAX_OFFSET, ("maxTexelGatherOffset must be at least " + de::toString((int)SPEC_MIN_MAX_OFFSET)).c_str());
1229 }
1230
1231 // Initialize texture.
1232 textureBinding = createTexture();
1233
1234 // Check image format support.
1235 // This should happen earlier but it's easier to retrieve texture parameters once created and this is not expected to fail.
1236 #ifndef CTS_USES_VULKANSC
1237 if (m_baseParams.levelMode != LevelMode::NORMAL)
1238 {
1239 const auto format = vk::mapTextureFormat(m_baseParams.textureFormat);
1240 const auto bindingType = textureBinding->getType();
1241 const auto imageViewType = textureTypeToImageViewType(bindingType);
1242 const auto imageType = viewTypeToImageType(imageViewType);
1243 const vk::VkImageUsageFlags usageFlags = textureUsageFlags();
1244 const vk::VkImageCreateFlags imageCreateFlags = textureCreateFlags(imageViewType, m_baseParams.sparseCase);
1245
1246 const vk::VkPhysicalDeviceImageFormatInfo2 formatInfo =
1247 {
1248 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // VkStructureType sType;
1249 nullptr, // const void* pNext;
1250 format, // VkFormat format;
1251 imageType, // VkImageType type;
1252 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1253 usageFlags, // VkImageUsageFlags usage;
1254 imageCreateFlags, // VkImageCreateFlags flags;
1255 };
1256
1257 vk::VkTextureLODGatherFormatPropertiesAMD lodGatherProperties =
1258 {
1259 vk::VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD, // VkStructureType sType;
1260 nullptr, // void* pNext;
1261 VK_FALSE, // VkBool32 supportsTextureGatherLODBiasAMD;
1262 };
1263
1264 vk::VkImageFormatProperties2 properties2 = vk::initVulkanStructure();
1265 properties2.pNext = &lodGatherProperties;
1266
1267 const auto retCode = m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties2(m_context.getPhysicalDevice(), &formatInfo, &properties2);
1268
1269 if (retCode != vk::VK_SUCCESS && retCode != vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
1270 TCU_FAIL("vkGetPhysicalDeviceImageFormatProperties2 returned " + de::toString(retCode));
1271
1272 if (retCode == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
1273 TCU_THROW(NotSupportedError, "Format does not support the required parameters");
1274
1275 if (!lodGatherProperties.supportsTextureGatherLODBiasAMD)
1276 TCU_THROW(NotSupportedError, "Format does not support texture gather LOD/Bias operations");
1277 }
1278 #endif
1279
1280 if (m_baseParams.textureSwizzle.isSome())
1281 {
1282 const tcu::Vector<TextureSwizzleComponent, 4>& swizzle = m_baseParams.textureSwizzle.getSwizzle();
1283
1284 const vk::VkComponentMapping components =
1285 {
1286 getTextureSwizzleComponent(swizzle[0]),
1287 getTextureSwizzleComponent(swizzle[1]),
1288 getTextureSwizzleComponent(swizzle[2]),
1289 getTextureSwizzleComponent(swizzle[3])
1290 };
1291
1292 textureParams.componentMapping = components;
1293 }
1294
1295 // Set base mip level and mode.
1296 if (m_baseParams.levelMode == LevelMode::NORMAL)
1297 {
1298 textureParams.baseMipLevel = m_baseParams.baseLevel;
1299 }
1300 else
1301 {
1302 const auto textureType = textureBinding->getType();
1303 int levels = 0;
1304
1305 switch (textureType)
1306 {
1307 case TextureBinding::TYPE_1D: levels = textureBinding->get1D().getNumLevels(); break;
1308 case TextureBinding::TYPE_2D: levels = textureBinding->get2D().getNumLevels(); break;
1309 case TextureBinding::TYPE_3D: levels = textureBinding->get3D().getNumLevels(); break;
1310 case TextureBinding::TYPE_CUBE_MAP: levels = textureBinding->getCube().getNumLevels(); break;
1311 case TextureBinding::TYPE_1D_ARRAY: levels = textureBinding->get1DArray().getNumLevels(); break;
1312 case TextureBinding::TYPE_2D_ARRAY: levels = textureBinding->get2DArray().getNumLevels(); break;
1313 case TextureBinding::TYPE_CUBE_ARRAY: levels = textureBinding->getCubeArray().getNumLevels(); break;
1314 default:
1315 DE_ASSERT(false); break;
1316 }
1317
1318 DE_ASSERT(levels > 0);
1319 textureParams.minMaxLod = tcu::just(TextureBinding::MinMaxLod(0.0f, static_cast<float>(levels - 1)));
1320 }
1321
1322 textureBinding->setParameters(textureParams);
1323 m_textures.push_back(textureBinding);
1324
1325 log << TestLog::Message << "Texture base level is " << textureParams.baseMipLevel << TestLog::EndMessage
1326 << TestLog::Message << "s and t wrap modes are "
1327 << vk::mapWrapMode(m_baseParams.wrapS) << " and "
1328 << vk::mapWrapMode(m_baseParams.wrapT) << ", respectively" << TestLog::EndMessage
1329 << TestLog::Message << "Minification and magnification filter modes are "
1330 << vk::mapFilterMode(m_baseParams.minFilter) << " and "
1331 << vk::mapFilterMode(m_baseParams.magFilter) << ", respectively "
1332 << "(note that they should have no effect on gather result)"
1333 << TestLog::EndMessage
1334 << TestLog::Message << "Using texture swizzle " << m_baseParams.textureSwizzle << TestLog::EndMessage;
1335
1336 if (m_baseParams.shadowCompareMode != tcu::Sampler::COMPAREMODE_NONE)
1337 log << TestLog::Message << "Using texture compare func " << vk::mapCompareMode(m_baseParams.shadowCompareMode) << TestLog::EndMessage;
1338 }
1339
setupDefaultInputs(void)1340 void TextureGatherInstance::setupDefaultInputs (void)
1341 {
1342 const int numVertices = 4;
1343 const float position[4*2] =
1344 {
1345 -1.0f, -1.0f,
1346 -1.0f, +1.0f,
1347 +1.0f, -1.0f,
1348 +1.0f, +1.0f,
1349 };
1350 const float normalizedCoord[4*2] =
1351 {
1352 0.0f, 0.0f,
1353 0.0f, 1.0f,
1354 1.0f, 0.0f,
1355 1.0f, 1.0f,
1356 };
1357 const vector<float> texCoord = computeQuadTexCoord(m_currentIteration);
1358 const bool needNormalizedCoordInShader = m_baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC || isDepthFormat(m_baseParams.textureFormat);
1359
1360 addAttribute(0u, vk::VK_FORMAT_R32G32_SFLOAT, 2 * (deUint32)sizeof(float), numVertices, position);
1361
1362 if (texCoord.size() == 2*4)
1363 addAttribute(1u, vk::VK_FORMAT_R32G32_SFLOAT, 2 * (deUint32)sizeof(float), numVertices, texCoord.data());
1364 else if (texCoord.size() == 3*4)
1365 addAttribute(1u, vk::VK_FORMAT_R32G32B32_SFLOAT, 3 * (deUint32)sizeof(float), numVertices, texCoord.data());
1366 else
1367 DE_ASSERT(false);
1368
1369 if (needNormalizedCoordInShader)
1370 addAttribute(2u, vk::VK_FORMAT_R32G32_SFLOAT, 2 * (deUint32)sizeof(float), numVertices, normalizedCoord);
1371 }
1372
iterate(void)1373 tcu::TestStatus TextureGatherInstance::iterate (void)
1374 {
1375 TestLog& log = m_context.getTestContext().getLog();
1376 const tcu::ScopedLogSection iterationSection (log, "Iteration" + de::toString(m_currentIteration), "Iteration " + de::toString(m_currentIteration));
1377
1378 // Render.
1379
1380 {
1381 const deUint32 numVertices = 4;
1382 const deUint32 numTriangles = 2;
1383 const deUint16 indices[6] = { 0, 1, 2, 2, 1, 3 };
1384 const vector<float> texCoord = computeQuadTexCoord(m_currentIteration);
1385
1386 if (texCoord.size() == 2*4)
1387 {
1388 Vec2 texCoordVec[4];
1389 computeTexCoordVecs(texCoord, texCoordVec);
1390 log << TestLog::Message << "Texture coordinates run from " << texCoordVec[0] << " to " << texCoordVec[3] << TestLog::EndMessage;
1391 }
1392 else if (texCoord.size() == 3*4)
1393 {
1394 Vec3 texCoordVec[4];
1395 computeTexCoordVecs(texCoord, texCoordVec);
1396 log << TestLog::Message << "Texture coordinates run from " << texCoordVec[0] << " to " << texCoordVec[3] << TestLog::EndMessage;
1397 }
1398 else
1399 DE_ASSERT(false);
1400
1401 m_vertexShaderName = "vert";
1402 m_fragmentShaderName = "frag_" + de::toString(m_currentIteration);
1403
1404 setup();
1405
1406 render(numVertices, numTriangles, indices);
1407 }
1408
1409 // Verify result.
1410 bool result = verify(m_currentIteration, getResultImage().getAccess());
1411 #ifdef CTS_USES_VULKANSC
1412 if (m_context.getTestContext().getCommandLine().isSubProcess())
1413 #endif // CTS_USES_VULKANSC
1414 {
1415 if (!result)
1416 return tcu::TestStatus::fail("Result verification failed");
1417 }
1418
1419 m_currentIteration++;
1420 if (m_currentIteration == getNumIterations())
1421 return tcu::TestStatus::pass("Pass");
1422 else
1423 return tcu::TestStatus::incomplete();
1424 }
1425
setupUniforms(const tcu::Vec4 &)1426 void TextureGatherInstance::setupUniforms (const tcu::Vec4&)
1427 {
1428 deUint32 binding = 0;
1429
1430 useSampler(binding++, 0u);
1431
1432 if (m_baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC)
1433 addUniform(binding++, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::Vec2), RENDER_SIZE.asFloat().getPtr());
1434
1435 if (m_baseParams.offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
1436 {
1437 if (m_baseParams.gatherType == GATHERTYPE_OFFSET)
1438 {
1439 const GatherArgs& gatherArgs = getGatherArgs(m_currentIteration);
1440 addUniform(binding++, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::IVec2), gatherArgs.offsets[0].getPtr());
1441 }
1442 else if (m_baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC)
1443 {
1444 const IVec2& offsetRange = getOffsetRange(m_baseParams.offsetSize, m_context.getDeviceProperties().limits);
1445 addUniform(binding++, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::IVec2), offsetRange.getPtr());
1446 }
1447 else
1448 DE_ASSERT(false);
1449 }
1450 }
1451
1452 template <typename TexViewT, typename TexCoordT>
verify(const ConstPixelBufferAccess & rendered,const TexViewT & texture,const TexCoordT (& texCoords)[4],const GatherArgs & gatherArgs) const1453 bool TextureGatherInstance::verify (const ConstPixelBufferAccess& rendered,
1454 const TexViewT& texture,
1455 const TexCoordT (&texCoords)[4],
1456 const GatherArgs& gatherArgs) const
1457 {
1458 TestLog& log = m_context.getTestContext().getLog();
1459
1460 {
1461 DE_ASSERT(m_colorBufferFormat.order == tcu::TextureFormat::RGBA);
1462 DE_ASSERT(m_colorBufferFormat.type == tcu::TextureFormat::UNORM_INT8 ||
1463 m_colorBufferFormat.type == tcu::TextureFormat::UNSIGNED_INT8 ||
1464 m_colorBufferFormat.type == tcu::TextureFormat::SIGNED_INT8);
1465
1466 const MovePtr<PixelOffsets> pixelOffsets = makePixelOffsetsFunctor(m_baseParams.gatherType, gatherArgs, getOffsetRange(m_baseParams.offsetSize, m_context.getDeviceProperties().limits));
1467 const tcu::PixelFormat pixelFormat = tcu::PixelFormat(8,8,8,8);
1468 const IVec4 colorBits = tcu::max(TextureTestUtil::getBitsVec(pixelFormat) - 1, tcu::IVec4(0));
1469 const IVec3 coordBits = m_baseParams.textureType == TEXTURETYPE_2D ? IVec3(20,20,0)
1470 : m_baseParams.textureType == TEXTURETYPE_CUBE ? IVec3(10,10,10)
1471 : m_baseParams.textureType == TEXTURETYPE_2D_ARRAY ? IVec3(20,20,20)
1472 : IVec3(-1);
1473 const IVec3 uvwBits = m_baseParams.textureType == TEXTURETYPE_2D ? IVec3(7,7,0)
1474 : m_baseParams.textureType == TEXTURETYPE_CUBE ? IVec3(6,6,0)
1475 : m_baseParams.textureType == TEXTURETYPE_2D_ARRAY ? IVec3(7,7,7)
1476 : IVec3(-1);
1477 tcu::Sampler sampler;
1478 sampler.wrapS = m_baseParams.wrapS;
1479 sampler.wrapT = m_baseParams.wrapT;
1480 sampler.compare = m_baseParams.shadowCompareMode;
1481 sampler.seamlessCubeMap = true;
1482
1483 if (isDepthFormat(m_baseParams.textureFormat))
1484 {
1485 tcu::TexComparePrecision comparePrec;
1486 comparePrec.coordBits = coordBits;
1487 comparePrec.uvwBits = uvwBits;
1488 comparePrec.referenceBits = 16;
1489 comparePrec.resultBits = pixelFormat.redBits-1;
1490
1491 return verifyGatherOffsetsCompare(log, rendered, texture, texCoords, sampler, comparePrec, PixelCompareRefZDefault(RENDER_SIZE), *pixelOffsets);
1492 }
1493 else
1494 {
1495 const int componentNdx = de::max(0, gatherArgs.componentNdx);
1496
1497 if (isUnormFormatType(m_baseParams.textureFormat.type))
1498 {
1499 tcu::LookupPrecision lookupPrec;
1500 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(colorBits);
1501 lookupPrec.coordBits = coordBits;
1502 lookupPrec.uvwBits = uvwBits;
1503 lookupPrec.colorMask = TextureTestUtil::getCompareMask(pixelFormat);
1504 return verifyGatherOffsets<float>(log, rendered, texture, texCoords, sampler, lookupPrec, componentNdx, *pixelOffsets);
1505 }
1506 else if (isUIntFormatType(m_baseParams.textureFormat.type) || isSIntFormatType(m_baseParams.textureFormat.type))
1507 {
1508 tcu::IntLookupPrecision lookupPrec;
1509 lookupPrec.colorThreshold = UVec4(0);
1510 lookupPrec.coordBits = coordBits;
1511 lookupPrec.uvwBits = uvwBits;
1512 lookupPrec.colorMask = TextureTestUtil::getCompareMask(pixelFormat);
1513
1514 if (isUIntFormatType(m_baseParams.textureFormat.type))
1515 return verifyGatherOffsets<deUint32>(log, rendered, texture, texCoords, sampler, lookupPrec, componentNdx, *pixelOffsets);
1516 else if (isSIntFormatType(m_baseParams.textureFormat.type))
1517 return verifyGatherOffsets<deInt32>(log, rendered, texture, texCoords, sampler, lookupPrec, componentNdx, *pixelOffsets);
1518 else
1519 {
1520 DE_ASSERT(false);
1521 return false;
1522 }
1523 }
1524 else
1525 {
1526 DE_ASSERT(false);
1527 return false;
1528 }
1529 }
1530 }
1531 }
1532
genVertexShaderSource(bool requireGpuShader5,int numTexCoordComponents,bool useNormalizedCoordInput)1533 glu::VertexSource genVertexShaderSource (bool requireGpuShader5, int numTexCoordComponents, bool useNormalizedCoordInput)
1534 {
1535 DE_ASSERT(numTexCoordComponents == 2 || numTexCoordComponents == 3);
1536
1537 const string texCoordType = "vec" + de::toString(numTexCoordComponents);
1538 std::ostringstream vert;
1539
1540 vert << "#version 310 es\n";
1541
1542 if (requireGpuShader5)
1543 vert << "#extension GL_EXT_gpu_shader5 : require\n";
1544
1545 vert << "\n"
1546 "layout (location = 0) in highp vec2 a_position;\n"
1547 "layout (location = 1) in highp " << texCoordType << " a_texCoord;\n";
1548
1549 if (useNormalizedCoordInput)
1550 vert << "layout (location = 2) in highp vec2 a_normalizedCoord; // (0,0) to (1,1)\n";
1551
1552 vert << "\n"
1553 "layout (location = 0) out highp " << texCoordType << " v_texCoord;\n";
1554
1555 if (useNormalizedCoordInput)
1556 vert << "layout (location = 1) out highp vec2 v_normalizedCoord;\n";
1557
1558 vert << "\n"
1559 "void main (void)\n"
1560 "{\n"
1561 " gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0);\n"
1562 " v_texCoord = a_texCoord;\n";
1563
1564 if (useNormalizedCoordInput)
1565 vert << " v_normalizedCoord = a_normalizedCoord;\n";
1566
1567 vert << "}\n";
1568
1569 return glu::VertexSource(vert.str());
1570 }
1571
genFragmentShaderSource(bool requireGpuShader5,int numTexCoordComponents,glu::DataType samplerType,const string & funcCall,bool useNormalizedCoordInput,bool usePixCoord,OffsetSize offsetSize,const ImageBackingMode sparseCase,LevelMode levelMode)1572 glu::FragmentSource genFragmentShaderSource (bool requireGpuShader5,
1573 int numTexCoordComponents,
1574 glu::DataType samplerType,
1575 const string& funcCall,
1576 bool useNormalizedCoordInput,
1577 bool usePixCoord,
1578 OffsetSize offsetSize,
1579 const ImageBackingMode sparseCase,
1580 LevelMode levelMode)
1581 {
1582 DE_ASSERT(glu::isDataTypeSampler(samplerType));
1583 DE_ASSERT(de::inRange(numTexCoordComponents, 2, 3));
1584 DE_ASSERT(!usePixCoord || useNormalizedCoordInput);
1585
1586 const string texCoordType = "vec" + de::toString(numTexCoordComponents);
1587 deUint32 binding = 0;
1588 std::ostringstream frag;
1589 const string outType = glu::getDataTypeName(getSamplerGatherResultType(samplerType));
1590
1591 frag << "#version 450\n";
1592
1593 if (sparseCase == ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE)
1594 frag << "#extension GL_ARB_sparse_texture2 : require\n";
1595
1596 if (levelMode != LevelMode::NORMAL)
1597 frag << "#extension GL_AMD_texture_gather_bias_lod : require\n";
1598
1599 if (requireGpuShader5)
1600 frag << "#extension GL_EXT_gpu_shader5 : require\n";
1601
1602 frag << "\n"
1603 "layout (location = 0) out mediump " << outType << " o_color;\n"
1604 "\n"
1605 "layout (location = 0) in highp " << texCoordType << " v_texCoord;\n";
1606
1607 if (useNormalizedCoordInput)
1608 frag << "layout (location = 1) in highp vec2 v_normalizedCoord;\n";
1609
1610 frag << "\n"
1611 "layout (binding = " << binding++ << ") uniform highp " << glu::getDataTypeName(samplerType) << " u_sampler;\n";
1612
1613 if (usePixCoord)
1614 frag << "layout (binding = " << binding++ << ") uniform viewportSize { highp vec2 u_viewportSize; };\n";
1615
1616 if (offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
1617 frag << "layout (binding = " << binding++ << ") uniform offset { highp ivec2 u_offset; };\n";
1618
1619 frag << "\n"
1620 "void main(void)\n"
1621 "{\n";
1622
1623 if (usePixCoord)
1624 frag << " ivec2 pixCoord = ivec2(v_normalizedCoord*u_viewportSize);\n";
1625
1626 if (sparseCase == ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE)
1627 {
1628 // Texel declaration
1629 frag << "\t" << outType << " texel;\n";
1630 frag << "\tint success = " << funcCall << ";\n";
1631
1632 // Check sparse validity, and handle each case
1633 frag << "\tif (sparseTexelsResidentARB(success))\n"
1634 << "\t\to_color = texel;\n"
1635 << "\telse\n"
1636 << "\t\to_color = " << outType << "(0.0, 0.0, 0.0, 1.0);\n";
1637 }
1638 else
1639 {
1640 frag << "\t\to_color = " << funcCall << ";\n";
1641 }
1642
1643 frag << "}\n";
1644
1645 return glu::FragmentSource(frag.str());
1646 }
1647
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)1648 string genGatherFuncCall (GatherType gatherType,
1649 const tcu::TextureFormat& textureFormat,
1650 const GatherArgs& gatherArgs,
1651 LevelMode levelMode,
1652 deUint32 baseLevel,
1653 const string& refZExpr,
1654 const IVec2& offsetRange,
1655 int indentationDepth,
1656 OffsetSize offsetSize,
1657 const ImageBackingMode sparseCase)
1658 {
1659 string result;
1660 string levelStr;
1661
1662 if (levelMode != LevelMode::NORMAL)
1663 {
1664 levelStr = de::toString(baseLevel) + ".0";
1665 }
1666
1667 if (sparseCase == ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE)
1668 {
1669 if (levelMode == LevelMode::NORMAL || levelMode == LevelMode::AMD_BIAS)
1670 {
1671 switch (gatherType)
1672 {
1673 case GATHERTYPE_BASIC:
1674 result += "sparseTextureGatherARB";
1675 break;
1676 case GATHERTYPE_OFFSET: // \note Fallthrough.
1677 case GATHERTYPE_OFFSET_DYNAMIC:
1678 result += "sparseTextureGatherOffsetARB";
1679 break;
1680 case GATHERTYPE_OFFSETS:
1681 result += "sparseTextureGatherOffsetsARB";
1682 break;
1683 default:
1684 DE_ASSERT(false);
1685 }
1686 }
1687 else // LevelMode::AMD_LOD
1688 {
1689 switch (gatherType)
1690 {
1691 case GATHERTYPE_BASIC:
1692 result += "sparseTextureGatherLodAMD";
1693 break;
1694 case GATHERTYPE_OFFSET: // \note Fallthrough.
1695 case GATHERTYPE_OFFSET_DYNAMIC:
1696 result += "sparseTextureGatherLodOffsetAMD";
1697 break;
1698 case GATHERTYPE_OFFSETS:
1699 result += "sparseTextureGatherLodOffsetsAMD";
1700 break;
1701 default:
1702 DE_ASSERT(false);
1703 }
1704 }
1705 }
1706 else
1707 {
1708 if (levelMode == LevelMode::NORMAL || levelMode == LevelMode::AMD_BIAS)
1709 {
1710 switch (gatherType)
1711 {
1712 case GATHERTYPE_BASIC:
1713 result += "textureGather";
1714 break;
1715 case GATHERTYPE_OFFSET: // \note Fallthrough.
1716 case GATHERTYPE_OFFSET_DYNAMIC:
1717 result += "textureGatherOffset";
1718 break;
1719 case GATHERTYPE_OFFSETS:
1720 result += "textureGatherOffsets";
1721 break;
1722 default:
1723 DE_ASSERT(false);
1724 }
1725 }
1726 else // LevelMode::AMD_LOD
1727 {
1728 switch (gatherType)
1729 {
1730 case GATHERTYPE_BASIC:
1731 result += "textureGatherLodAMD";
1732 break;
1733 case GATHERTYPE_OFFSET: // \note Fallthrough.
1734 case GATHERTYPE_OFFSET_DYNAMIC:
1735 result += "textureGatherLodOffsetAMD";
1736 break;
1737 case GATHERTYPE_OFFSETS:
1738 result += "textureGatherLodOffsetsAMD";
1739 break;
1740 default:
1741 DE_ASSERT(false);
1742 }
1743 }
1744 }
1745
1746 result += "(u_sampler, v_texCoord";
1747
1748 if (isDepthFormat(textureFormat))
1749 {
1750 DE_ASSERT(gatherArgs.componentNdx < 0);
1751 result += ", " + refZExpr;
1752 }
1753
1754 if (levelMode == LevelMode::AMD_LOD)
1755 {
1756 result += ", " + levelStr;
1757 }
1758
1759 if (gatherType == GATHERTYPE_OFFSET ||
1760 gatherType == GATHERTYPE_OFFSET_DYNAMIC ||
1761 gatherType == GATHERTYPE_OFFSETS)
1762 {
1763 result += ", ";
1764 switch (gatherType)
1765 {
1766 case GATHERTYPE_OFFSET:
1767 if (offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
1768 result += "u_offset";
1769 else
1770 result += "ivec2" + de::toString(gatherArgs.offsets[0]);
1771 break;
1772
1773 case GATHERTYPE_OFFSET_DYNAMIC:
1774 if (offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
1775 result += "pixCoord.yx % ivec2(u_offset.y - u_offset.x + 1) + u_offset.x";
1776 else
1777 result += "pixCoord.yx % ivec2(" + de::toString(offsetRange.y() - offsetRange.x() + 1) + ") + " + de::toString(offsetRange.x());
1778 break;
1779
1780 case GATHERTYPE_OFFSETS:
1781 DE_ASSERT(offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM);
1782 result += "ivec2[4](\n"
1783 + string(indentationDepth, '\t') + "\tivec2" + de::toString(gatherArgs.offsets[0]) + ",\n"
1784 + string(indentationDepth, '\t') + "\tivec2" + de::toString(gatherArgs.offsets[1]) + ",\n"
1785 + string(indentationDepth, '\t') + "\tivec2" + de::toString(gatherArgs.offsets[2]) + ",\n"
1786 + string(indentationDepth, '\t') + "\tivec2" + de::toString(gatherArgs.offsets[3]) + ")\n"
1787 + string(indentationDepth, '\t') + "\t";
1788 break;
1789
1790 default:
1791 DE_ASSERT(false);
1792 }
1793 }
1794
1795 if (sparseCase == ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE)
1796 result += ", texel";
1797
1798 if (gatherArgs.componentNdx >= 0)
1799 {
1800 DE_ASSERT(gatherArgs.componentNdx < 4);
1801 result += ", " + de::toString(gatherArgs.componentNdx);
1802 }
1803
1804 if (levelMode == LevelMode::AMD_BIAS)
1805 {
1806 result += ", " + levelStr;
1807 }
1808
1809 result += ")";
1810
1811 return result;
1812 }
1813
1814 // \todo [2016-07-08 pyry] Re-use programs if sources are identical
1815
genGatherPrograms(vk::SourceCollections & programCollection,const GatherCaseBaseParams & baseParams,const vector<GatherArgs> & iterations)1816 void genGatherPrograms (vk::SourceCollections& programCollection, const GatherCaseBaseParams& baseParams, const vector<GatherArgs>& iterations)
1817 {
1818 const int numIterations = (int)iterations.size();
1819 const string refZExpr = "v_normalizedCoord.x";
1820 const IVec2& offsetRange = baseParams.offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? getOffsetRange(baseParams.offsetSize) : IVec2(0);
1821 const bool usePixCoord = baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC;
1822 const bool useNormalizedCoord = usePixCoord || isDepthFormat(baseParams.textureFormat);
1823 const bool isDynamicOffset = baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC;
1824 const bool isShadow = isDepthFormat(baseParams.textureFormat);
1825 const glu::DataType samplerType = getSamplerType(baseParams.textureType, baseParams.textureFormat);
1826 const int numDims = getNumTextureSamplingDimensions(baseParams.textureType);
1827 glu::VertexSource vert = genVertexShaderSource(requireGpuShader5(baseParams.gatherType, baseParams.offsetSize), numDims, isDynamicOffset || isShadow);
1828
1829 // Check sampler type is valid.
1830 if (baseParams.levelMode != LevelMode::NORMAL)
1831 {
1832 std::vector<glu::DataType> validSamplerTypes =
1833 {
1834 glu::TYPE_SAMPLER_2D,
1835 glu::TYPE_SAMPLER_2D_ARRAY,
1836 glu::TYPE_INT_SAMPLER_2D,
1837 glu::TYPE_INT_SAMPLER_2D_ARRAY,
1838 glu::TYPE_UINT_SAMPLER_2D,
1839 glu::TYPE_UINT_SAMPLER_2D_ARRAY,
1840 };
1841
1842 if (baseParams.gatherType == GATHERTYPE_BASIC)
1843 {
1844 static const std::vector<glu::DataType> kAdditionalTypes =
1845 {
1846 glu::TYPE_SAMPLER_CUBE,
1847 glu::TYPE_SAMPLER_CUBE_ARRAY,
1848 glu::TYPE_INT_SAMPLER_CUBE,
1849 glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
1850 glu::TYPE_UINT_SAMPLER_CUBE,
1851 glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
1852 };
1853
1854 std::copy(begin(kAdditionalTypes), end(kAdditionalTypes), std::back_inserter(validSamplerTypes));
1855 }
1856
1857 const auto itr = std::find(begin(validSamplerTypes), end(validSamplerTypes), samplerType);
1858 DE_ASSERT(itr != end(validSamplerTypes));
1859 DE_UNREF(itr); // For release builds.
1860 }
1861
1862 programCollection.glslSources.add("vert") << vert;
1863
1864 for (int iterNdx = 0; iterNdx < numIterations; iterNdx++)
1865 {
1866 const GatherArgs& gatherArgs = iterations[iterNdx];
1867 const string funcCall = genGatherFuncCall(baseParams.gatherType, baseParams.textureFormat, gatherArgs, baseParams.levelMode, baseParams.baseLevel, refZExpr, offsetRange, 1, baseParams.offsetSize, baseParams.sparseCase);
1868 glu::FragmentSource frag = genFragmentShaderSource(requireGpuShader5(baseParams.gatherType, baseParams.offsetSize), numDims, samplerType, funcCall, useNormalizedCoord, usePixCoord, baseParams.offsetSize, baseParams.sparseCase, baseParams.levelMode);
1869
1870 programCollection.glslSources.add("frag_" + de::toString(iterNdx)) << frag;
1871 }
1872 }
1873
1874 // 2D
1875
1876 class TextureGather2DInstance : public TextureGatherInstance
1877 {
1878 public:
1879 TextureGather2DInstance (Context& context,
1880 const GatherCaseBaseParams& baseParams,
1881 const IVec2& textureSize,
1882 const vector<GatherArgs>& iterations);
1883 virtual ~TextureGather2DInstance (void);
1884
1885 protected:
getNumIterations(void) const1886 virtual int getNumIterations (void) const { return (int)m_iterations.size(); }
getGatherArgs(int iterationNdx) const1887 virtual GatherArgs getGatherArgs (int iterationNdx) const { return m_iterations[iterationNdx];}
1888
1889 virtual TextureBindingSp createTexture (void);
1890 virtual vector<float> computeQuadTexCoord (int iterationNdx) const;
1891 virtual bool verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const;
1892
1893 private:
1894 const IVec2 m_textureSize;
1895 const vector<GatherArgs> m_iterations;
1896
1897 tcu::Texture2D m_swizzledTexture;
1898 };
1899
TextureGather2DInstance(Context & context,const GatherCaseBaseParams & baseParams,const IVec2 & textureSize,const vector<GatherArgs> & iterations)1900 TextureGather2DInstance::TextureGather2DInstance (Context& context,
1901 const GatherCaseBaseParams& baseParams,
1902 const IVec2& textureSize,
1903 const vector<GatherArgs>& iterations)
1904 : TextureGatherInstance (context, baseParams)
1905 , m_textureSize (textureSize)
1906 , m_iterations (iterations)
1907 , m_swizzledTexture (tcu::TextureFormat(), 1, 1)
1908 {
1909 init();
1910 }
1911
~TextureGather2DInstance(void)1912 TextureGather2DInstance::~TextureGather2DInstance (void)
1913 {
1914 }
1915
computeQuadTexCoord(int) const1916 vector<float> TextureGather2DInstance::computeQuadTexCoord (int /* iterationNdx */) const
1917 {
1918 const bool biasMode = (m_baseParams.levelMode == LevelMode::AMD_BIAS);
1919 const auto bottomLeft = (biasMode ? Vec2(0.0f, 0.0f) : Vec2(-0.3f, -0.4f));
1920 const auto topRight = (biasMode ? Vec2(1.0f, 1.0f) : Vec2(1.5f, 1.6f));
1921 vector<float> res;
1922 TextureTestUtil::computeQuadTexCoord2D(res, bottomLeft, topRight);
1923 return res;
1924 }
1925
createTexture(void)1926 TextureBindingSp TextureGather2DInstance::createTexture (void)
1927 {
1928 TestLog& log = m_context.getTestContext().getLog();
1929 const tcu::TextureFormatInfo texFmtInfo = tcu::getTextureFormatInfo(m_baseParams.textureFormat);
1930 MovePtr<tcu::Texture2D> texture = MovePtr<tcu::Texture2D>(new tcu::Texture2D(m_baseParams.textureFormat, m_textureSize.x(), m_textureSize.y()));
1931 const tcu::Sampler sampler (m_baseParams.wrapS, m_baseParams.wrapT, tcu::Sampler::REPEAT_GL,
1932 m_baseParams.minFilter, m_baseParams.magFilter,
1933 0.0f /* LOD threshold */, true /* normalized coords */, m_baseParams.shadowCompareMode,
1934 0 /* compare channel */, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f) /* border color */, true /* seamless cube*/);
1935
1936 {
1937 const int levelBegin = ((m_baseParams.levelMode == LevelMode::NORMAL) ? m_baseParams.baseLevel : 0);
1938 const int levelEnd = texture->getNumLevels();
1939 DE_ASSERT(m_baseParams.baseLevel < texture->getNumLevels());
1940
1941 for (int levelNdx = levelBegin; levelNdx < levelEnd; levelNdx++)
1942 {
1943 texture->allocLevel(levelNdx);
1944 const PixelBufferAccess& level = texture->getLevel(levelNdx);
1945 fillWithRandomColorTiles(level, texFmtInfo.valueMin, texFmtInfo.valueMax, (deUint32)m_context.getTestContext().getCommandLine().getBaseSeed());
1946 log << TestLog::Image("InputTextureLevel" + de::toString(levelNdx), "Input texture, level " + de::toString(levelNdx), level)
1947 << TestLog::Message << "Note: texture level's size is " << IVec2(level.getWidth(), level.getHeight()) << TestLog::EndMessage;
1948 }
1949
1950 swizzleTexture(m_swizzledTexture, *texture, m_baseParams.textureSwizzle);
1951 }
1952
1953 return TextureBindingSp(new TextureBinding(texture.release(), sampler));
1954 }
1955
verify(int iterationNdx,const ConstPixelBufferAccess & rendered) const1956 bool TextureGather2DInstance::verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const
1957 {
1958 Vec2 texCoords[4];
1959 computeTexCoordVecs(computeQuadTexCoord(iterationNdx), texCoords);
1960 return TextureGatherInstance::verify(rendered, getOneLevelSubView(tcu::Texture2DView(m_swizzledTexture), m_baseParams.baseLevel), texCoords, m_iterations[iterationNdx]);
1961 }
1962
1963 class TextureGather2DCase : public TestCase
1964 {
1965 public:
1966 TextureGather2DCase (tcu::TestContext& testCtx,
1967 const string& name,
1968 const string& description,
1969 const GatherType gatherType,
1970 const OffsetSize offsetSize,
1971 const tcu::TextureFormat textureFormat,
1972 const tcu::Sampler::CompareMode shadowCompareMode,
1973 const tcu::Sampler::WrapMode wrapS,
1974 const tcu::Sampler::WrapMode wrapT,
1975 const MaybeTextureSwizzle& textureSwizzle,
1976 const tcu::Sampler::FilterMode minFilter,
1977 const tcu::Sampler::FilterMode magFilter,
1978 const LevelMode levelMode,
1979 const int baseLevel,
1980 const deUint32 flags,
1981 const IVec2& textureSize,
1982 const ImageBackingMode sparseCase);
1983 virtual ~TextureGather2DCase (void);
1984
1985 virtual void initPrograms (vk::SourceCollections& dst) const;
1986 virtual TestInstance* createInstance (Context& context) const;
1987 virtual void checkSupport (Context& context) const;
1988
1989 private:
1990 const GatherCaseBaseParams m_baseParams;
1991 const IVec2 m_textureSize;
1992 };
1993
TextureGather2DCase(tcu::TestContext & testCtx,const string & name,const string & description,const GatherType gatherType,const OffsetSize offsetSize,const tcu::TextureFormat textureFormat,const tcu::Sampler::CompareMode shadowCompareMode,const tcu::Sampler::WrapMode wrapS,const tcu::Sampler::WrapMode wrapT,const MaybeTextureSwizzle & textureSwizzle,const tcu::Sampler::FilterMode minFilter,const tcu::Sampler::FilterMode magFilter,const LevelMode levelMode,const int baseLevel,const deUint32 flags,const IVec2 & textureSize,const ImageBackingMode sparseCase)1994 TextureGather2DCase::TextureGather2DCase (tcu::TestContext& testCtx,
1995 const string& name,
1996 const string& description,
1997 const GatherType gatherType,
1998 const OffsetSize offsetSize,
1999 const tcu::TextureFormat textureFormat,
2000 const tcu::Sampler::CompareMode shadowCompareMode,
2001 const tcu::Sampler::WrapMode wrapS,
2002 const tcu::Sampler::WrapMode wrapT,
2003 const MaybeTextureSwizzle& textureSwizzle,
2004 const tcu::Sampler::FilterMode minFilter,
2005 const tcu::Sampler::FilterMode magFilter,
2006 const LevelMode levelMode,
2007 const int baseLevel,
2008 const deUint32 flags,
2009 const IVec2& textureSize,
2010 const ImageBackingMode sparseCase)
2011 : TestCase (testCtx, name, description)
2012 , m_baseParams (TEXTURETYPE_2D, gatherType, offsetSize, textureFormat, shadowCompareMode, wrapS, wrapT, textureSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, sparseCase)
2013 , m_textureSize (textureSize)
2014 {
2015 }
2016
~TextureGather2DCase(void)2017 TextureGather2DCase::~TextureGather2DCase (void)
2018 {
2019 }
2020
initPrograms(vk::SourceCollections & dst) const2021 void TextureGather2DCase::initPrograms (vk::SourceCollections& dst) const
2022 {
2023 const vector<GatherArgs> iterations = generateBasic2DCaseIterations(m_baseParams.gatherType,
2024 m_baseParams.levelMode,
2025 m_baseParams.textureFormat,
2026 m_baseParams.offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? getOffsetRange(m_baseParams.offsetSize) : IVec2(0));
2027
2028 genGatherPrograms(dst, m_baseParams, iterations);
2029 }
2030
createInstance(Context & context) const2031 TestInstance* TextureGather2DCase::createInstance (Context& context) const
2032 {
2033 const vector<GatherArgs> iterations = generateBasic2DCaseIterations(m_baseParams.gatherType,
2034 m_baseParams.levelMode,
2035 m_baseParams.textureFormat,
2036 getOffsetRange(m_baseParams.offsetSize, context.getDeviceProperties().limits));
2037
2038 return new TextureGather2DInstance(context, m_baseParams, m_textureSize, iterations);
2039 }
2040
checkSupport(Context & context) const2041 void TextureGather2DCase::checkSupport(Context& context) const
2042 {
2043 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_IMAGE_GATHER_EXTENDED);
2044 checkMutableComparisonSamplersSupport(context, m_baseParams);
2045 }
2046
2047 // 2D array
2048
2049 struct Gather2DArrayArgs
2050 {
2051 GatherArgs gatherArgs;
2052 int layerNdx;
2053
operator GatherArgsvkt::sr::__anonac2a49bc0111::Gather2DArrayArgs2054 operator GatherArgs() const { return gatherArgs; }
2055 };
2056
generate2DArrayCaseIterations(GatherType gatherType,LevelMode levelMode,const tcu::TextureFormat & textureFormat,const IVec2 & offsetRange,const IVec3 & textureSize)2057 vector<Gather2DArrayArgs> generate2DArrayCaseIterations (GatherType gatherType,
2058 LevelMode levelMode,
2059 const tcu::TextureFormat& textureFormat,
2060 const IVec2& offsetRange,
2061 const IVec3& textureSize)
2062 {
2063 const vector<GatherArgs> basicIterations = generateBasic2DCaseIterations(gatherType, levelMode, textureFormat, offsetRange);
2064 vector<Gather2DArrayArgs> iterations;
2065
2066 // \note Out-of-bounds layer indices are tested too.
2067 for (int layerNdx = -1; layerNdx < textureSize.z()+1; layerNdx++)
2068 {
2069 // Don't duplicate all cases for all layers.
2070 if (layerNdx == 0)
2071 {
2072 for (int basicNdx = 0; basicNdx < (int)basicIterations.size(); basicNdx++)
2073 {
2074 iterations.push_back(Gather2DArrayArgs());
2075 iterations.back().gatherArgs = basicIterations[basicNdx];
2076 iterations.back().layerNdx = layerNdx;
2077 }
2078 }
2079 else
2080 {
2081 // For other layers than 0, only test one component and one set of offsets per layer.
2082 for (int basicNdx = 0; basicNdx < (int)basicIterations.size(); basicNdx++)
2083 {
2084 if (isDepthFormat(textureFormat) || basicIterations[basicNdx].componentNdx == (layerNdx + 2) % 4)
2085 {
2086 iterations.push_back(Gather2DArrayArgs());
2087 iterations.back().gatherArgs = basicIterations[basicNdx];
2088 iterations.back().layerNdx = layerNdx;
2089 break;
2090 }
2091 }
2092 }
2093 }
2094
2095 return iterations;
2096 }
2097
2098 class TextureGather2DArrayInstance : public TextureGatherInstance
2099 {
2100 public:
2101 TextureGather2DArrayInstance (Context& context,
2102 const GatherCaseBaseParams& baseParams,
2103 const IVec3& textureSize,
2104 const vector<Gather2DArrayArgs>& iterations);
2105 virtual ~TextureGather2DArrayInstance (void);
2106
2107 protected:
getNumIterations(void) const2108 virtual int getNumIterations (void) const { return (int)m_iterations.size(); }
getGatherArgs(int iterationNdx) const2109 virtual GatherArgs getGatherArgs (int iterationNdx) const { return m_iterations[iterationNdx].gatherArgs; }
2110
2111 virtual TextureBindingSp createTexture (void);
2112 virtual vector<float> computeQuadTexCoord (int iterationNdx) const;
2113 virtual bool verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const;
2114
2115 private:
2116 const IVec3 m_textureSize;
2117 const vector<Gather2DArrayArgs> m_iterations;
2118
2119 tcu::Texture2DArray m_swizzledTexture;
2120 };
2121
TextureGather2DArrayInstance(Context & context,const GatherCaseBaseParams & baseParams,const IVec3 & textureSize,const vector<Gather2DArrayArgs> & iterations)2122 TextureGather2DArrayInstance::TextureGather2DArrayInstance (Context& context,
2123 const GatherCaseBaseParams& baseParams,
2124 const IVec3& textureSize,
2125 const vector<Gather2DArrayArgs>& iterations)
2126 : TextureGatherInstance (context, baseParams)
2127 , m_textureSize (textureSize)
2128 , m_iterations (iterations)
2129 , m_swizzledTexture (tcu::TextureFormat(), 1, 1, 1)
2130 {
2131 init();
2132 }
2133
~TextureGather2DArrayInstance(void)2134 TextureGather2DArrayInstance::~TextureGather2DArrayInstance (void)
2135 {
2136 }
2137
computeQuadTexCoord(int iterationNdx) const2138 vector<float> TextureGather2DArrayInstance::computeQuadTexCoord (int iterationNdx) const
2139 {
2140 const bool biasMode = (m_baseParams.levelMode == LevelMode::AMD_BIAS);
2141 const auto bottomLeft = (biasMode ? Vec2(0.0f, 0.0f) : Vec2(-0.3f, -0.4f));
2142 const auto topRight = (biasMode ? Vec2(1.0f, 1.0f) : Vec2(1.5f, 1.6f));
2143 vector<float> res;
2144 TextureTestUtil::computeQuadTexCoord2DArray(res, m_iterations[iterationNdx].layerNdx, bottomLeft, topRight);
2145 return res;
2146 }
2147
createTexture(void)2148 TextureBindingSp TextureGather2DArrayInstance::createTexture (void)
2149 {
2150 TestLog& log = m_context.getTestContext().getLog();
2151 const tcu::TextureFormatInfo texFmtInfo = tcu::getTextureFormatInfo(m_baseParams.textureFormat);
2152 MovePtr<tcu::Texture2DArray> texture = MovePtr<tcu::Texture2DArray>(new tcu::Texture2DArray(m_baseParams.textureFormat, m_textureSize.x(), m_textureSize.y(), m_textureSize.z()));
2153 const tcu::Sampler sampler (m_baseParams.wrapS, m_baseParams.wrapT, tcu::Sampler::REPEAT_GL,
2154 m_baseParams.minFilter, m_baseParams.magFilter,
2155 0.0f /* LOD threshold */, true /* normalized coords */, m_baseParams.shadowCompareMode,
2156 0 /* compare channel */, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f) /* border color */, true /* seamless cube*/);
2157
2158 {
2159 const int levelBegin = ((m_baseParams.levelMode == LevelMode::NORMAL) ? m_baseParams.baseLevel : 0);
2160 const int levelEnd = texture->getNumLevels();
2161 DE_ASSERT(m_baseParams.baseLevel < texture->getNumLevels());
2162
2163 for (int levelNdx = levelBegin; levelNdx < levelEnd; levelNdx++)
2164 {
2165 texture->allocLevel(levelNdx);
2166 const PixelBufferAccess& level = texture->getLevel(levelNdx);
2167 fillWithRandomColorTiles(level, texFmtInfo.valueMin, texFmtInfo.valueMax, (deUint32)m_context.getTestContext().getCommandLine().getBaseSeed());
2168
2169 log << TestLog::ImageSet("InputTextureLevel", "Input texture, level " + de::toString(levelNdx));
2170 for (int layerNdx = 0; layerNdx < m_textureSize.z(); layerNdx++)
2171 log << TestLog::Image("InputTextureLevel" + de::toString(layerNdx) + "Layer" + de::toString(layerNdx),
2172 "Layer " + de::toString(layerNdx),
2173 tcu::getSubregion(level, 0, 0, layerNdx, level.getWidth(), level.getHeight(), 1));
2174 log << TestLog::EndImageSet
2175 << TestLog::Message << "Note: texture level's size is " << IVec3(level.getWidth(), level.getHeight(), level.getDepth()) << TestLog::EndMessage;
2176 }
2177
2178 swizzleTexture(m_swizzledTexture, *texture, m_baseParams.textureSwizzle);
2179 }
2180
2181 return TextureBindingSp(new TextureBinding(texture.release(), sampler));
2182 }
2183
verify(int iterationNdx,const ConstPixelBufferAccess & rendered) const2184 bool TextureGather2DArrayInstance::verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const
2185 {
2186 Vec3 texCoords[4];
2187 computeTexCoordVecs(computeQuadTexCoord(iterationNdx), texCoords);
2188 return TextureGatherInstance::verify(rendered, getOneLevelSubView(tcu::Texture2DArrayView(m_swizzledTexture), m_baseParams.baseLevel), texCoords, m_iterations[iterationNdx].gatherArgs);
2189 }
2190
2191 class TextureGather2DArrayCase : public TestCase
2192 {
2193 public:
2194 TextureGather2DArrayCase (tcu::TestContext& testCtx,
2195 const string& name,
2196 const string& description,
2197 const GatherType gatherType,
2198 const OffsetSize offsetSize,
2199 const tcu::TextureFormat textureFormat,
2200 const tcu::Sampler::CompareMode shadowCompareMode,
2201 const tcu::Sampler::WrapMode wrapS,
2202 const tcu::Sampler::WrapMode wrapT,
2203 const MaybeTextureSwizzle& textureSwizzle,
2204 const tcu::Sampler::FilterMode minFilter,
2205 const tcu::Sampler::FilterMode magFilter,
2206 const LevelMode levelMode,
2207 const int baseLevel,
2208 const deUint32 flags,
2209 const IVec3& textureSize,
2210 const ImageBackingMode sparseCase);
2211 virtual ~TextureGather2DArrayCase (void);
2212
2213 virtual void initPrograms (vk::SourceCollections& dst) const;
2214 virtual TestInstance* createInstance (Context& context) const;
2215 virtual void checkSupport (Context& context) const;
2216
2217 private:
2218 const GatherCaseBaseParams m_baseParams;
2219 const IVec3 m_textureSize;
2220 };
2221
TextureGather2DArrayCase(tcu::TestContext & testCtx,const string & name,const string & description,const GatherType gatherType,const OffsetSize offsetSize,const tcu::TextureFormat textureFormat,const tcu::Sampler::CompareMode shadowCompareMode,const tcu::Sampler::WrapMode wrapS,const tcu::Sampler::WrapMode wrapT,const MaybeTextureSwizzle & textureSwizzle,const tcu::Sampler::FilterMode minFilter,const tcu::Sampler::FilterMode magFilter,const LevelMode levelMode,const int baseLevel,const deUint32 flags,const IVec3 & textureSize,const ImageBackingMode sparseCase)2222 TextureGather2DArrayCase::TextureGather2DArrayCase (tcu::TestContext& testCtx,
2223 const string& name,
2224 const string& description,
2225 const GatherType gatherType,
2226 const OffsetSize offsetSize,
2227 const tcu::TextureFormat textureFormat,
2228 const tcu::Sampler::CompareMode shadowCompareMode,
2229 const tcu::Sampler::WrapMode wrapS,
2230 const tcu::Sampler::WrapMode wrapT,
2231 const MaybeTextureSwizzle& textureSwizzle,
2232 const tcu::Sampler::FilterMode minFilter,
2233 const tcu::Sampler::FilterMode magFilter,
2234 const LevelMode levelMode,
2235 const int baseLevel,
2236 const deUint32 flags,
2237 const IVec3& textureSize,
2238 const ImageBackingMode sparseCase)
2239 : TestCase (testCtx, name, description)
2240 , m_baseParams (TEXTURETYPE_2D_ARRAY, gatherType, offsetSize, textureFormat, shadowCompareMode, wrapS, wrapT, textureSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, sparseCase)
2241 , m_textureSize (textureSize)
2242 {
2243 }
2244
~TextureGather2DArrayCase(void)2245 TextureGather2DArrayCase::~TextureGather2DArrayCase (void)
2246 {
2247 }
2248
initPrograms(vk::SourceCollections & dst) const2249 void TextureGather2DArrayCase::initPrograms (vk::SourceCollections& dst) const
2250 {
2251 const vector<Gather2DArrayArgs> iterations = generate2DArrayCaseIterations(m_baseParams.gatherType,
2252 m_baseParams.levelMode,
2253 m_baseParams.textureFormat,
2254 m_baseParams.offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? getOffsetRange(m_baseParams.offsetSize) : IVec2(0),
2255 m_textureSize);
2256
2257 genGatherPrograms(dst, m_baseParams, vector<GatherArgs>(iterations.begin(), iterations.end()));
2258 }
2259
createInstance(Context & context) const2260 TestInstance* TextureGather2DArrayCase::createInstance (Context& context) const
2261 {
2262 const vector<Gather2DArrayArgs> iterations = generate2DArrayCaseIterations(m_baseParams.gatherType,
2263 m_baseParams.levelMode,
2264 m_baseParams.textureFormat,
2265 getOffsetRange(m_baseParams.offsetSize, context.getDeviceProperties().limits),
2266 m_textureSize);
2267
2268 return new TextureGather2DArrayInstance(context, m_baseParams, m_textureSize, iterations);
2269 }
2270
checkSupport(Context & context) const2271 void TextureGather2DArrayCase::checkSupport(Context& context) const
2272 {
2273 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_IMAGE_GATHER_EXTENDED);
2274 checkMutableComparisonSamplersSupport(context, m_baseParams);
2275 }
2276
2277 // Cube
2278
2279 struct GatherCubeArgs
2280 {
2281 GatherArgs gatherArgs;
2282 tcu::CubeFace face;
2283
operator GatherArgsvkt::sr::__anonac2a49bc0111::GatherCubeArgs2284 operator GatherArgs() const { return gatherArgs; }
2285 };
2286
generateCubeCaseIterations(GatherType gatherType,LevelMode levelMode,const tcu::TextureFormat & textureFormat,const IVec2 & offsetRange)2287 vector<GatherCubeArgs> generateCubeCaseIterations (GatherType gatherType, LevelMode levelMode, const tcu::TextureFormat& textureFormat, const IVec2& offsetRange)
2288 {
2289 const vector<GatherArgs> basicIterations = generateBasic2DCaseIterations(gatherType, levelMode, textureFormat, offsetRange);
2290 vector<GatherCubeArgs> iterations;
2291
2292 for (int cubeFaceI = 0; cubeFaceI < tcu::CUBEFACE_LAST; cubeFaceI++)
2293 {
2294 const tcu::CubeFace cubeFace = (tcu::CubeFace)cubeFaceI;
2295
2296 // Don't duplicate all cases for all faces.
2297 if (cubeFaceI == 0)
2298 {
2299 for (int basicNdx = 0; basicNdx < (int)basicIterations.size(); basicNdx++)
2300 {
2301 iterations.push_back(GatherCubeArgs());
2302 iterations.back().gatherArgs = basicIterations[basicNdx];
2303 iterations.back().face = cubeFace;
2304 }
2305 }
2306 else
2307 {
2308 // For other faces than first, only test one component per face.
2309 for (int basicNdx = 0; basicNdx < (int)basicIterations.size(); basicNdx++)
2310 {
2311 if (isDepthFormat(textureFormat) || basicIterations[basicNdx].componentNdx == cubeFaceI % 4)
2312 {
2313 iterations.push_back(GatherCubeArgs());
2314 iterations.back().gatherArgs = basicIterations[basicNdx];
2315 iterations.back().face = cubeFace;
2316 break;
2317 }
2318 }
2319 }
2320 }
2321
2322 return iterations;
2323 }
2324
2325 class TextureGatherCubeInstance : public TextureGatherInstance
2326 {
2327 public:
2328 TextureGatherCubeInstance (Context& context,
2329 const GatherCaseBaseParams& baseParams,
2330 const int textureSize,
2331 const vector<GatherCubeArgs>& iterations);
2332 virtual ~TextureGatherCubeInstance (void);
2333
2334 protected:
getNumIterations(void) const2335 virtual int getNumIterations (void) const { return (int)m_iterations.size(); }
getGatherArgs(int iterationNdx) const2336 virtual GatherArgs getGatherArgs (int iterationNdx) const { return m_iterations[iterationNdx].gatherArgs; }
2337
2338 virtual TextureBindingSp createTexture (void);
2339 virtual vector<float> computeQuadTexCoord (int iterationNdx) const;
2340 virtual bool verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const;
2341
2342 private:
2343 const int m_textureSize;
2344 const vector<GatherCubeArgs> m_iterations;
2345
2346 tcu::TextureCube m_swizzledTexture;
2347 };
2348
TextureGatherCubeInstance(Context & context,const GatherCaseBaseParams & baseParams,const int textureSize,const vector<GatherCubeArgs> & iterations)2349 TextureGatherCubeInstance::TextureGatherCubeInstance (Context& context,
2350 const GatherCaseBaseParams& baseParams,
2351 const int textureSize,
2352 const vector<GatherCubeArgs>& iterations)
2353 : TextureGatherInstance (context, baseParams)
2354 , m_textureSize (textureSize)
2355 , m_iterations (iterations)
2356 , m_swizzledTexture (tcu::TextureFormat(), 1)
2357 {
2358 init();
2359 }
2360
~TextureGatherCubeInstance(void)2361 TextureGatherCubeInstance::~TextureGatherCubeInstance (void)
2362 {
2363 }
2364
computeQuadTexCoord(int iterationNdx) const2365 vector<float> TextureGatherCubeInstance::computeQuadTexCoord (int iterationNdx) const
2366 {
2367 const bool biasMode = (m_baseParams.levelMode == LevelMode::AMD_BIAS);
2368 const bool corners = (m_baseParams.flags & GATHERCASE_DONT_SAMPLE_CUBE_CORNERS) == 0;
2369 const Vec2 minC = (biasMode ? Vec2(-1.0f) : (corners ? Vec2(-1.2f) : Vec2(-0.6f, -1.2f)));
2370 const Vec2 maxC = (biasMode ? Vec2( 1.0f) : (corners ? Vec2( 1.2f) : Vec2( 0.6f, 1.2f)));
2371 vector<float> res;
2372 TextureTestUtil::computeQuadTexCoordCube(res, m_iterations[iterationNdx].face, minC, maxC);
2373 return res;
2374 }
2375
createTexture(void)2376 TextureBindingSp TextureGatherCubeInstance::createTexture (void)
2377 {
2378 TestLog& log = m_context.getTestContext().getLog();
2379 const tcu::TextureFormatInfo texFmtInfo = tcu::getTextureFormatInfo(m_baseParams.textureFormat);
2380 MovePtr<tcu::TextureCube> texture = MovePtr<tcu::TextureCube>(new tcu::TextureCube(m_baseParams.textureFormat, m_textureSize));
2381 const tcu::Sampler sampler (m_baseParams.wrapS, m_baseParams.wrapT, tcu::Sampler::REPEAT_GL,
2382 m_baseParams.minFilter, m_baseParams.magFilter,
2383 0.0f /* LOD threshold */, true /* normalized coords */, m_baseParams.shadowCompareMode,
2384 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */);
2385
2386 {
2387 const int levelBegin = ((m_baseParams.levelMode == LevelMode::NORMAL) ? m_baseParams.baseLevel : 0);
2388 const int levelEnd = texture->getNumLevels();
2389 DE_ASSERT(m_baseParams.baseLevel < texture->getNumLevels());
2390
2391 for (int levelNdx = levelBegin; levelNdx < levelEnd; levelNdx++)
2392 {
2393 log << TestLog::ImageSet("InputTextureLevel" + de::toString(levelNdx), "Input texture, level " + de::toString(levelNdx));
2394
2395 for (int cubeFaceI = 0; cubeFaceI < tcu::CUBEFACE_LAST; cubeFaceI++)
2396 {
2397 const tcu::CubeFace cubeFace = (tcu::CubeFace)cubeFaceI;
2398 texture->allocLevel(cubeFace, levelNdx);
2399 const PixelBufferAccess& levelFace = texture->getLevelFace(levelNdx, cubeFace);
2400 fillWithRandomColorTiles(levelFace, texFmtInfo.valueMin, texFmtInfo.valueMax, (deUint32)m_context.getTestContext().getCommandLine().getBaseSeed() ^ (deUint32)cubeFaceI);
2401
2402 log << TestLog::Image("InputTextureLevel" + de::toString(levelNdx) + "Face" + de::toString((int)cubeFace), de::toString(cubeFace), levelFace);
2403 }
2404
2405 log << TestLog::EndImageSet
2406 << TestLog::Message << "Note: texture level's size is " << texture->getLevelFace(levelNdx, tcu::CUBEFACE_NEGATIVE_X).getWidth() << TestLog::EndMessage;
2407 }
2408
2409 swizzleTexture(m_swizzledTexture, *texture, m_baseParams.textureSwizzle);
2410 }
2411
2412 return TextureBindingSp(new TextureBinding(texture.release(), sampler));
2413 }
2414
verify(int iterationNdx,const ConstPixelBufferAccess & rendered) const2415 bool TextureGatherCubeInstance::verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const
2416 {
2417 Vec3 texCoords[4];
2418 computeTexCoordVecs(computeQuadTexCoord(iterationNdx), texCoords);
2419 return TextureGatherInstance::verify(rendered, getOneLevelSubView(tcu::TextureCubeView(m_swizzledTexture), m_baseParams.baseLevel), texCoords, m_iterations[iterationNdx].gatherArgs);
2420 }
2421
2422 // \note Cube case always uses just basic textureGather(); offset versions are not defined for cube maps.
2423 class TextureGatherCubeCase : public TestCase
2424 {
2425 public:
2426 TextureGatherCubeCase (tcu::TestContext& testCtx,
2427 const string& name,
2428 const string& description,
2429 const tcu::TextureFormat textureFormat,
2430 const tcu::Sampler::CompareMode shadowCompareMode,
2431 const tcu::Sampler::WrapMode wrapS,
2432 const tcu::Sampler::WrapMode wrapT,
2433 const MaybeTextureSwizzle& textureSwizzle,
2434 const tcu::Sampler::FilterMode minFilter,
2435 const tcu::Sampler::FilterMode magFilter,
2436 const LevelMode levelMode,
2437 const int baseLevel,
2438 const deUint32 flags,
2439 const int textureSize,
2440 const ImageBackingMode sparseCase);
2441 virtual ~TextureGatherCubeCase (void);
2442
2443 virtual void initPrograms (vk::SourceCollections& dst) const;
2444 virtual TestInstance* createInstance (Context& context) const;
2445 virtual void checkSupport (Context& context) const;
2446
2447 private:
2448 const GatherCaseBaseParams m_baseParams;
2449 const int m_textureSize;
2450 };
2451
TextureGatherCubeCase(tcu::TestContext & testCtx,const string & name,const string & description,const tcu::TextureFormat textureFormat,const tcu::Sampler::CompareMode shadowCompareMode,const tcu::Sampler::WrapMode wrapS,const tcu::Sampler::WrapMode wrapT,const MaybeTextureSwizzle & textureSwizzle,const tcu::Sampler::FilterMode minFilter,const tcu::Sampler::FilterMode magFilter,const LevelMode levelMode,const int baseLevel,const deUint32 flags,const int textureSize,const ImageBackingMode sparseCase)2452 TextureGatherCubeCase::TextureGatherCubeCase (tcu::TestContext& testCtx,
2453 const string& name,
2454 const string& description,
2455 const tcu::TextureFormat textureFormat,
2456 const tcu::Sampler::CompareMode shadowCompareMode,
2457 const tcu::Sampler::WrapMode wrapS,
2458 const tcu::Sampler::WrapMode wrapT,
2459 const MaybeTextureSwizzle& textureSwizzle,
2460 const tcu::Sampler::FilterMode minFilter,
2461 const tcu::Sampler::FilterMode magFilter,
2462 const LevelMode levelMode,
2463 const int baseLevel,
2464 const deUint32 flags,
2465 const int textureSize,
2466 const ImageBackingMode sparseCase)
2467 : TestCase (testCtx, name, description)
2468 , m_baseParams (TEXTURETYPE_CUBE, GATHERTYPE_BASIC, OFFSETSIZE_NONE, textureFormat, shadowCompareMode, wrapS, wrapT, textureSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, sparseCase)
2469 , m_textureSize (textureSize)
2470 {
2471 }
2472
~TextureGatherCubeCase(void)2473 TextureGatherCubeCase::~TextureGatherCubeCase (void)
2474 {
2475 }
2476
initPrograms(vk::SourceCollections & dst) const2477 void TextureGatherCubeCase::initPrograms (vk::SourceCollections& dst) const
2478 {
2479 const vector<GatherCubeArgs> iterations = generateCubeCaseIterations(m_baseParams.gatherType,
2480 m_baseParams.levelMode,
2481 m_baseParams.textureFormat,
2482 m_baseParams.offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? getOffsetRange(m_baseParams.offsetSize) : IVec2(0));
2483
2484 genGatherPrograms(dst, m_baseParams, vector<GatherArgs>(iterations.begin(), iterations.end()));
2485 }
2486
createInstance(Context & context) const2487 TestInstance* TextureGatherCubeCase::createInstance (Context& context) const
2488 {
2489 const vector<GatherCubeArgs> iterations = generateCubeCaseIterations(m_baseParams.gatherType,
2490 m_baseParams.levelMode,
2491 m_baseParams.textureFormat,
2492 getOffsetRange(m_baseParams.offsetSize, context.getDeviceProperties().limits));
2493
2494 return new TextureGatherCubeInstance(context, m_baseParams, m_textureSize, iterations);
2495 }
2496
checkSupport(Context & context) const2497 void TextureGatherCubeCase::checkSupport(Context& context) const
2498 {
2499 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_IMAGE_GATHER_EXTENDED);
2500 checkMutableComparisonSamplersSupport(context, m_baseParams);
2501 }
2502
2503 class TextureGatherTests : public tcu::TestCaseGroup
2504 {
2505 public:
2506 TextureGatherTests (tcu::TestContext& context);
2507 virtual ~TextureGatherTests (void);
2508 virtual void init (void);
2509
2510 private:
2511 TextureGatherTests (const TextureGatherTests&); // not allowed!
2512 TextureGatherTests& operator= (const TextureGatherTests&); // not allowed!
2513 };
2514
TextureGatherTests(tcu::TestContext & context)2515 TextureGatherTests::TextureGatherTests (tcu::TestContext& context)
2516 : TestCaseGroup(context, "texture_gather", "textureGather* tests")
2517 {
2518 }
2519
~TextureGatherTests(void)2520 TextureGatherTests::~TextureGatherTests (void)
2521 {
2522 }
2523
makeTextureGatherCase(TextureType textureType,tcu::TestContext & testCtx,const string & name,const string & description,GatherType gatherType,OffsetSize offsetSize,tcu::TextureFormat textureFormat,tcu::Sampler::CompareMode shadowCompareMode,tcu::Sampler::WrapMode wrapS,tcu::Sampler::WrapMode wrapT,const MaybeTextureSwizzle & texSwizzle,tcu::Sampler::FilterMode minFilter,tcu::Sampler::FilterMode magFilter,LevelMode levelMode,int baseLevel,const IVec3 & textureSize,deUint32 flags=0,const ImageBackingMode sparseCase=ShaderRenderCaseInstance::IMAGE_BACKING_MODE_REGULAR)2524 static inline TestCase* makeTextureGatherCase (TextureType textureType,
2525 tcu::TestContext& testCtx,
2526 const string& name,
2527 const string& description,
2528 GatherType gatherType,
2529 OffsetSize offsetSize,
2530 tcu::TextureFormat textureFormat,
2531 tcu::Sampler::CompareMode shadowCompareMode,
2532 tcu::Sampler::WrapMode wrapS,
2533 tcu::Sampler::WrapMode wrapT,
2534 const MaybeTextureSwizzle& texSwizzle,
2535 tcu::Sampler::FilterMode minFilter,
2536 tcu::Sampler::FilterMode magFilter,
2537 LevelMode levelMode,
2538 int baseLevel,
2539 const IVec3& textureSize,
2540 deUint32 flags = 0,
2541 const ImageBackingMode sparseCase = ShaderRenderCaseInstance::IMAGE_BACKING_MODE_REGULAR)
2542 {
2543 switch (textureType)
2544 {
2545 case TEXTURETYPE_2D:
2546 return new TextureGather2DCase(testCtx, name, description, gatherType, offsetSize, textureFormat, shadowCompareMode,
2547 wrapS, wrapT, texSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, textureSize.swizzle(0, 1), sparseCase);
2548
2549 case TEXTURETYPE_2D_ARRAY:
2550 return new TextureGather2DArrayCase(testCtx, name, description, gatherType, offsetSize, textureFormat, shadowCompareMode,
2551 wrapS, wrapT, texSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, textureSize, sparseCase);
2552
2553 case TEXTURETYPE_CUBE:
2554 DE_ASSERT(gatherType == GATHERTYPE_BASIC);
2555 DE_ASSERT(offsetSize == OFFSETSIZE_NONE);
2556 return new TextureGatherCubeCase(testCtx, name, description, textureFormat, shadowCompareMode,
2557 wrapS, wrapT, texSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, textureSize.x(), sparseCase);
2558
2559 default:
2560 DE_ASSERT(false);
2561 return DE_NULL;
2562 }
2563 }
2564
compareModeName(tcu::Sampler::CompareMode mode)2565 static inline const char* compareModeName (tcu::Sampler::CompareMode mode)
2566 {
2567 switch (mode)
2568 {
2569 case tcu::Sampler::COMPAREMODE_LESS: return "less";
2570 case tcu::Sampler::COMPAREMODE_LESS_OR_EQUAL: return "less_or_equal";
2571 case tcu::Sampler::COMPAREMODE_GREATER: return "greater";
2572 case tcu::Sampler::COMPAREMODE_GREATER_OR_EQUAL: return "greater_or_equal";
2573 case tcu::Sampler::COMPAREMODE_EQUAL: return "equal";
2574 case tcu::Sampler::COMPAREMODE_NOT_EQUAL: return "not_equal";
2575 case tcu::Sampler::COMPAREMODE_ALWAYS: return "always";
2576 case tcu::Sampler::COMPAREMODE_NEVER: return "never";
2577 default: DE_ASSERT(false); return DE_NULL;
2578 }
2579 }
2580
init(void)2581 void TextureGatherTests::init (void)
2582 {
2583 const struct
2584 {
2585 const char* name;
2586 TextureType type;
2587 } textureTypes[] =
2588 {
2589 { "2d", TEXTURETYPE_2D },
2590 { "2d_array", TEXTURETYPE_2D_ARRAY },
2591 { "cube", TEXTURETYPE_CUBE }
2592 };
2593
2594 const struct
2595 {
2596 const char* name;
2597 tcu::TextureFormat format;
2598 } formats[] =
2599 {
2600 { "rgba8", tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) },
2601 { "rgba8ui", tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT8) },
2602 { "rgba8i", tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT8) },
2603 { "depth32f", tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT) }
2604 };
2605
2606 const struct
2607 {
2608 const char* name;
2609 IVec3 size;
2610 } textureSizes[] =
2611 {
2612 { "size_pot", IVec3(64, 64, 3) },
2613 { "size_npot", IVec3(17, 23, 3) }
2614 };
2615
2616 const struct
2617 {
2618 const char* name;
2619 tcu::Sampler::WrapMode mode;
2620 } wrapModes[] =
2621 {
2622 { "clamp_to_edge", tcu::Sampler::CLAMP_TO_EDGE },
2623 { "repeat", tcu::Sampler::REPEAT_GL },
2624 { "mirrored_repeat", tcu::Sampler::MIRRORED_REPEAT_GL }
2625 };
2626
2627 for (int gatherTypeI = 0; gatherTypeI < GATHERTYPE_LAST; gatherTypeI++)
2628 {
2629 const GatherType gatherType = (GatherType)gatherTypeI;
2630 TestCaseGroup* const gatherTypeGroup = new TestCaseGroup(m_testCtx, gatherTypeName(gatherType), gatherTypeDescription(gatherType));
2631 addChild(gatherTypeGroup);
2632
2633 for (int offsetSizeI = 0; offsetSizeI < OFFSETSIZE_LAST; offsetSizeI++)
2634 {
2635 const OffsetSize offsetSize = (OffsetSize)offsetSizeI;
2636 if ((gatherType == GATHERTYPE_BASIC) != (offsetSize == OFFSETSIZE_NONE))
2637 continue;
2638
2639 if (gatherType == GATHERTYPE_OFFSETS && offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM) // \note offsets argument must be compile-time constant
2640 continue;
2641
2642 TestCaseGroup* const offsetSizeGroup = offsetSize == OFFSETSIZE_NONE ?
2643 gatherTypeGroup :
2644 new TestCaseGroup(m_testCtx,
2645 offsetSize == OFFSETSIZE_MINIMUM_REQUIRED ? "min_required_offset"
2646 : offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? "implementation_offset"
2647 : DE_NULL,
2648 offsetSize == OFFSETSIZE_MINIMUM_REQUIRED ? "Use offsets within Vulkan minimum required range"
2649 : offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? "Use offsets within the implementation range"
2650 : DE_NULL);
2651
2652 if (offsetSizeGroup != gatherTypeGroup)
2653 gatherTypeGroup->addChild(offsetSizeGroup);
2654
2655 for (int textureTypeNdx = 0; textureTypeNdx < DE_LENGTH_OF_ARRAY(textureTypes); textureTypeNdx++)
2656 {
2657 const TextureType textureType = textureTypes[textureTypeNdx].type;
2658
2659 if (textureType == TEXTURETYPE_CUBE && gatherType != GATHERTYPE_BASIC)
2660 continue;
2661
2662 TestCaseGroup* const textureTypeGroup = new TestCaseGroup(m_testCtx, textureTypes[textureTypeNdx].name, "");
2663 offsetSizeGroup->addChild(textureTypeGroup);
2664
2665 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
2666 {
2667 const tcu::TextureFormat& format = formats[formatNdx].format;
2668 TestCaseGroup* const formatGroup = new TestCaseGroup(m_testCtx, formats[formatNdx].name, "");
2669 textureTypeGroup->addChild(formatGroup);
2670
2671 for (int noCornersI = 0; noCornersI <= ((textureType == TEXTURETYPE_CUBE)?1:0); noCornersI++)
2672 {
2673 const bool noCorners = noCornersI!= 0;
2674 TestCaseGroup* const cornersGroup = noCorners
2675 ? new TestCaseGroup(m_testCtx, "no_corners", "Test case variants that don't sample around cube map corners")
2676 : formatGroup;
2677
2678 if (formatGroup != cornersGroup)
2679 formatGroup->addChild(cornersGroup);
2680
2681 for (int textureSizeNdx = 0; textureSizeNdx < DE_LENGTH_OF_ARRAY(textureSizes); textureSizeNdx++)
2682 {
2683 const IVec3& textureSize = textureSizes[textureSizeNdx].size;
2684 TestCaseGroup* const textureSizeGroup = new TestCaseGroup(m_testCtx, textureSizes[textureSizeNdx].name, "");
2685 cornersGroup->addChild(textureSizeGroup);
2686
2687 for (int compareModeI = 0; compareModeI < tcu::Sampler::COMPAREMODE_LAST; compareModeI++)
2688 {
2689 const tcu::Sampler::CompareMode compareMode = (tcu::Sampler::CompareMode)compareModeI;
2690
2691 if ((compareMode != tcu::Sampler::COMPAREMODE_NONE) != isDepthFormat(format))
2692 continue;
2693
2694 if (compareMode != tcu::Sampler::COMPAREMODE_NONE &&
2695 compareMode != tcu::Sampler::COMPAREMODE_LESS &&
2696 compareMode != tcu::Sampler::COMPAREMODE_GREATER)
2697 continue;
2698
2699 TestCaseGroup* const compareModeGroup = compareMode == tcu::Sampler::COMPAREMODE_NONE ?
2700 textureSizeGroup :
2701 new TestCaseGroup(m_testCtx,
2702 (string() + "compare_" + compareModeName(compareMode)).c_str(),
2703 "");
2704 if (compareModeGroup != textureSizeGroup)
2705 textureSizeGroup->addChild(compareModeGroup);
2706
2707 for (int wrapCaseNdx = 0; wrapCaseNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapCaseNdx++)
2708 {
2709 const int wrapSNdx = wrapCaseNdx;
2710 const int wrapTNdx = (wrapCaseNdx + 1) % DE_LENGTH_OF_ARRAY(wrapModes);
2711 const tcu::Sampler::WrapMode wrapS = wrapModes[wrapSNdx].mode;
2712 const tcu::Sampler::WrapMode wrapT = wrapModes[wrapTNdx].mode;
2713
2714 const string caseName = string() + wrapModes[wrapSNdx].name + "_" + wrapModes[wrapTNdx].name;
2715
2716 compareModeGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, caseName.c_str(), "", gatherType, offsetSize, format, compareMode, wrapS, wrapT,
2717 MaybeTextureSwizzle::createNoneTextureSwizzle(), tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, LevelMode::NORMAL, 0, textureSize,
2718 noCorners ? GATHERCASE_DONT_SAMPLE_CUBE_CORNERS : 0));
2719 #ifndef CTS_USES_VULKANSC
2720 compareModeGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, "sparse_" + caseName, "", gatherType, offsetSize, format, compareMode, wrapS, wrapT,
2721 MaybeTextureSwizzle::createNoneTextureSwizzle(), tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, LevelMode::NORMAL, 0, textureSize,
2722 noCorners ? GATHERCASE_DONT_SAMPLE_CUBE_CORNERS : 0, ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE));
2723 #endif // CTS_USES_VULKANSC
2724 }
2725 }
2726 }
2727 }
2728
2729 if (offsetSize != OFFSETSIZE_MINIMUM_REQUIRED || gatherType == GATHERTYPE_OFFSETS) // Don't test all features for both offset size types, as they should be rather orthogonal.
2730 {
2731 if (!isDepthFormat(format))
2732 {
2733 TestCaseGroup* const swizzleGroup = new TestCaseGroup(m_testCtx, "texture_swizzle", "");
2734 formatGroup->addChild(swizzleGroup);
2735
2736 DE_STATIC_ASSERT(TEXTURESWIZZLECOMPONENT_R == 0);
2737 for (int swizzleCaseNdx = 0; swizzleCaseNdx < TEXTURESWIZZLECOMPONENT_LAST; swizzleCaseNdx++)
2738 {
2739 MaybeTextureSwizzle swizzle = MaybeTextureSwizzle::createSomeTextureSwizzle();
2740 string caseName;
2741
2742 for (int i = 0; i < 4; i++)
2743 {
2744 swizzle.getSwizzle()[i] = (TextureSwizzleComponent)((swizzleCaseNdx + i) % (int)TEXTURESWIZZLECOMPONENT_LAST);
2745 caseName += (i > 0 ? "_" : "") + de::toLower(de::toString(swizzle.getSwizzle()[i]));
2746 }
2747
2748 swizzleGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, caseName.c_str(), "", gatherType, offsetSize, format,
2749 tcu::Sampler::COMPAREMODE_NONE, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2750 swizzle, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, LevelMode::NORMAL, 0, IVec3(64, 64, 3)));
2751 #ifndef CTS_USES_VULKANSC
2752 swizzleGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, "sparse_" + caseName, "", gatherType, offsetSize, format,
2753 tcu::Sampler::COMPAREMODE_NONE, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2754 swizzle, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, LevelMode::NORMAL, 0, IVec3(64, 64, 3), 0, ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE));
2755 #endif // CTS_USES_VULKANSC
2756 }
2757 }
2758
2759 {
2760 TestCaseGroup* const filterModeGroup = new TestCaseGroup(m_testCtx, "filter_mode", "Test that filter modes have no effect");
2761 formatGroup->addChild(filterModeGroup);
2762
2763 const struct
2764 {
2765 const char* name;
2766 tcu::Sampler::FilterMode filter;
2767 } magFilters[] =
2768 {
2769 { "linear", tcu::Sampler::LINEAR },
2770 { "nearest", tcu::Sampler::NEAREST }
2771 };
2772
2773 const struct
2774 {
2775 const char* name;
2776 tcu::Sampler::FilterMode filter;
2777 } minFilters[] =
2778 {
2779 // \note Don't test NEAREST here, as it's covered by other cases.
2780 { "linear", tcu::Sampler::LINEAR },
2781 { "nearest_mipmap_nearest", tcu::Sampler::NEAREST_MIPMAP_NEAREST },
2782 { "nearest_mipmap_linear", tcu::Sampler::NEAREST_MIPMAP_LINEAR },
2783 { "linear_mipmap_nearest", tcu::Sampler::LINEAR_MIPMAP_NEAREST },
2784 { "linear_mipmap_linear", tcu::Sampler::LINEAR_MIPMAP_LINEAR },
2785 };
2786
2787 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilters); minFilterNdx++)
2788 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilters); magFilterNdx++)
2789 {
2790 const tcu::Sampler::FilterMode minFilter = minFilters[minFilterNdx].filter;
2791 const tcu::Sampler::FilterMode magFilter = magFilters[magFilterNdx].filter;
2792 const tcu::Sampler::CompareMode compareMode = isDepthFormat(format) ? tcu::Sampler::COMPAREMODE_LESS : tcu::Sampler::COMPAREMODE_NONE;
2793
2794 if ((isUnormFormatType(format.type) || isDepthFormat(format)) && magFilter == tcu::Sampler::NEAREST)
2795 continue; // Covered by other cases.
2796 if ((isUIntFormatType(format.type) || isSIntFormatType(format.type)) &&
2797 (magFilter != tcu::Sampler::NEAREST || minFilter != tcu::Sampler::NEAREST_MIPMAP_NEAREST))
2798 continue;
2799
2800 const string caseName = string() + "min_" + minFilters[minFilterNdx].name + "_mag_" + magFilters[magFilterNdx].name;
2801
2802 filterModeGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, caseName.c_str(), "", gatherType, offsetSize, format, compareMode,
2803 tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, MaybeTextureSwizzle::createNoneTextureSwizzle(),
2804 minFilter, magFilter, LevelMode::NORMAL, 0, IVec3(64, 64, 3)));
2805 #ifndef CTS_USES_VULKANSC
2806 filterModeGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, "sparse_" + caseName, "", gatherType, offsetSize, format, compareMode,
2807 tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, MaybeTextureSwizzle::createNoneTextureSwizzle(),
2808 minFilter, magFilter, LevelMode::NORMAL, 0, IVec3(64, 64, 3), 0, ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE));
2809 #endif // CTS_USES_VULKANSC
2810 }
2811 }
2812
2813 {
2814 TestCaseGroup* const baseLevelGroup = new TestCaseGroup(m_testCtx, "base_level", "");
2815 formatGroup->addChild(baseLevelGroup);
2816
2817 for (int baseLevel = 1; baseLevel <= 2; baseLevel++)
2818 {
2819 static const struct
2820 {
2821 const std::string suffix;
2822 LevelMode levelMode;
2823 } levelModes[] =
2824 {
2825 { "", LevelMode::NORMAL },
2826 #ifndef CTS_USES_VULKANSC
2827 { "_amd_bias", LevelMode::AMD_BIAS },
2828 { "_amd_lod", LevelMode::AMD_LOD },
2829 #endif
2830 };
2831
2832 for (int modeIdx = 0; modeIdx < DE_LENGTH_OF_ARRAY(levelModes); ++modeIdx)
2833 {
2834 const auto& mode = levelModes[modeIdx].levelMode;
2835
2836 // Not supported for these sampler types.
2837 if (isDepthFormat(format) && mode != LevelMode::NORMAL)
2838 continue;
2839
2840 const string caseName = "level_" + de::toString(baseLevel) + levelModes[modeIdx].suffix;
2841 const tcu::Sampler::CompareMode compareMode = isDepthFormat(format) ? tcu::Sampler::COMPAREMODE_LESS : tcu::Sampler::COMPAREMODE_NONE;
2842 // The minFilter mode may need to be NEAREST_MIPMAP_NEAREST so the sampler creating code will not limit maxLod.
2843 const auto minFilter = ((mode == LevelMode::NORMAL) ? tcu::Sampler::NEAREST : tcu::Sampler::NEAREST_MIPMAP_NEAREST);
2844 baseLevelGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, caseName.c_str(), "", gatherType, offsetSize, format,
2845 compareMode, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2846 MaybeTextureSwizzle::createNoneTextureSwizzle(), minFilter, tcu::Sampler::NEAREST,
2847 mode, baseLevel, IVec3(64, 64, 3)));
2848 #ifndef CTS_USES_VULKANSC
2849 baseLevelGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, "sparse_" + caseName, "", gatherType, offsetSize, format,
2850 compareMode, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2851 MaybeTextureSwizzle::createNoneTextureSwizzle(), minFilter, tcu::Sampler::NEAREST,
2852 mode, baseLevel, IVec3(64, 64, 3), 0, ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE));
2853 #endif // CTS_USES_VULKANSC
2854 }
2855 }
2856 }
2857 }
2858 }
2859 }
2860 }
2861 }
2862 }
2863
2864 } // anonymous
2865
createTextureGatherTests(tcu::TestContext & testCtx)2866 tcu::TestCaseGroup* createTextureGatherTests (tcu::TestContext& testCtx)
2867 {
2868 return new TextureGatherTests(testCtx);
2869 }
2870
2871 } // sr
2872 } // vkt
2873