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