1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
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
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 * \brief GLSL textureGather[Offset[s]] tests.
24 *//*--------------------------------------------------------------------*/
26 #include "vktShaderRenderTextureGatherTests.hpp"
27 #include "vktShaderRender.hpp"
28 #include "vkImageUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "gluTextureUtil.hpp"
31 #include "tcuTexture.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "tcuSurface.hpp"
34 #include "tcuTestLog.hpp"
35 #include "tcuVectorUtil.hpp"
36 #include "tcuTexLookupVerifier.hpp"
37 #include "tcuTexCompareVerifier.hpp"
38 #include "tcuPixelFormat.hpp"
39 #include "tcuCommandLine.hpp"
40 #include "deUniquePtr.hpp"
41 #include "deStringUtil.hpp"
42 #include "deRandom.hpp"
47 using tcu::ConstPixelBufferAccess;
48 using tcu::PixelBufferAccess;
69 typedef ShaderRenderCaseInstance::ImageBackingMode ImageBackingMode;
73 SPEC_MAX_MIN_OFFSET = -8,
74 SPEC_MIN_MAX_OFFSET = 7
86 // \note TextureTestUtil functions are copied from glsTextureTestUtil
87 namespace TextureTestUtil
90 inline tcu::IVec4 getBitsVec (const tcu::PixelFormat& format)
92 return tcu::IVec4(format.redBits, format.greenBits, format.blueBits, format.alphaBits);
95 inline tcu::BVec4 getCompareMask (const tcu::PixelFormat& format)
97 return tcu::BVec4(format.redBits > 0,
100 format.alphaBits > 0);
103 void computeQuadTexCoord2D (std::vector<float>& dst, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
107 dst[0] = bottomLeft.x(); dst[1] = bottomLeft.y();
108 dst[2] = bottomLeft.x(); dst[3] = topRight.y();
109 dst[4] = topRight.x(); dst[5] = bottomLeft.y();
110 dst[6] = topRight.x(); dst[7] = topRight.y();
113 void computeQuadTexCoord2DArray (std::vector<float>& dst, int layerNdx, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
117 dst[0] = bottomLeft.x(); dst[ 1] = bottomLeft.y(); dst[ 2] = (float)layerNdx;
118 dst[3] = bottomLeft.x(); dst[ 4] = topRight.y(); dst[ 5] = (float)layerNdx;
119 dst[6] = topRight.x(); dst[ 7] = bottomLeft.y(); dst[ 8] = (float)layerNdx;
120 dst[9] = topRight.x(); dst[10] = topRight.y(); dst[11] = (float)layerNdx;
123 void computeQuadTexCoordCube (std::vector<float>& dst, tcu::CubeFace face, const tcu::Vec2& bottomLeft, const tcu::Vec2& topRight)
134 case tcu::CUBEFACE_NEGATIVE_X: mRow = 0; sRow = 2; tRow = 1; mSign = -1.0f; tSign = -1.0f; break;
135 case tcu::CUBEFACE_POSITIVE_X: mRow = 0; sRow = 2; tRow = 1; sSign = -1.0f; tSign = -1.0f; break;
136 case tcu::CUBEFACE_NEGATIVE_Y: mRow = 1; sRow = 0; tRow = 2; mSign = -1.0f; tSign = -1.0f; break;
137 case tcu::CUBEFACE_POSITIVE_Y: mRow = 1; sRow = 0; tRow = 2; break;
138 case tcu::CUBEFACE_NEGATIVE_Z: mRow = 2; sRow = 0; tRow = 1; mSign = -1.0f; sSign = -1.0f; tSign = -1.0f; break;
139 case tcu::CUBEFACE_POSITIVE_Z: mRow = 2; sRow = 0; tRow = 1; tSign = -1.0f; break;
152 dst[0+sRow] = sSign * bottomLeft.x();
153 dst[3+sRow] = sSign * bottomLeft.x();
154 dst[6+sRow] = sSign * topRight.x();
155 dst[9+sRow] = sSign * topRight.x();
157 dst[0+tRow] = tSign * bottomLeft.y();
158 dst[3+tRow] = tSign * topRight.y();
159 dst[6+tRow] = tSign * bottomLeft.y();
160 dst[9+tRow] = tSign * topRight.y();
165 // Round-to-zero int division, because pre-c++11 it's somewhat implementation-defined for negative values.
166 static inline int divRoundToZero (int a, int b)
168 return de::abs(a) / de::abs(b) * deSign32(a) * deSign32(b);
171 static void fillWithRandomColorTiles (const PixelBufferAccess& dst, const Vec4& minVal, const Vec4& maxVal, deUint32 seed)
173 const int numCols = dst.getWidth() >= 7 ? 7 : dst.getWidth();
174 const int numRows = dst.getHeight() >= 5 ? 5 : dst.getHeight();
175 de::Random rnd (seed);
177 for (int slice = 0; slice < dst.getDepth(); slice++)
178 for (int row = 0; row < numRows; row++)
179 for (int col = 0; col < numCols; col++)
181 const int yBegin = (row+0)*dst.getHeight()/numRows;
182 const int yEnd = (row+1)*dst.getHeight()/numRows;
183 const int xBegin = (col+0)*dst.getWidth()/numCols;
184 const int xEnd = (col+1)*dst.getWidth()/numCols;
185 const Vec4 color = tcu::randomVector<float, 4>(rnd, minVal, maxVal);
187 tcu::clear(tcu::getSubregion(dst, xBegin, yBegin, slice, xEnd-xBegin, yEnd-yBegin, 1), color);
191 static inline bool isDepthFormat (const tcu::TextureFormat& fmt)
193 return fmt.order == tcu::TextureFormat::D || fmt.order == tcu::TextureFormat::DS;
196 static inline bool isUnormFormatType (tcu::TextureFormat::ChannelType type)
198 return type == tcu::TextureFormat::UNORM_INT8 ||
199 type == tcu::TextureFormat::UNORM_INT16 ||
200 type == tcu::TextureFormat::UNORM_INT32;
203 static inline bool isSIntFormatType (tcu::TextureFormat::ChannelType type)
205 return type == tcu::TextureFormat::SIGNED_INT8 ||
206 type == tcu::TextureFormat::SIGNED_INT16 ||
207 type == tcu::TextureFormat::SIGNED_INT32;
210 static inline bool isUIntFormatType (tcu::TextureFormat::ChannelType type)
212 return type == tcu::TextureFormat::UNSIGNED_INT8 ||
213 type == tcu::TextureFormat::UNSIGNED_INT16 ||
214 type == tcu::TextureFormat::UNSIGNED_INT32;
217 enum TextureSwizzleComponent
219 TEXTURESWIZZLECOMPONENT_R = 0,
220 TEXTURESWIZZLECOMPONENT_G,
221 TEXTURESWIZZLECOMPONENT_B,
222 TEXTURESWIZZLECOMPONENT_A,
223 TEXTURESWIZZLECOMPONENT_ZERO,
224 TEXTURESWIZZLECOMPONENT_ONE,
226 TEXTURESWIZZLECOMPONENT_LAST
229 static std::ostream& operator<< (std::ostream& stream, TextureSwizzleComponent comp)
233 case TEXTURESWIZZLECOMPONENT_R: return stream << "RED";
234 case TEXTURESWIZZLECOMPONENT_G: return stream << "GREEN";
235 case TEXTURESWIZZLECOMPONENT_B: return stream << "BLUE";
236 case TEXTURESWIZZLECOMPONENT_A: return stream << "ALPHA";
237 case TEXTURESWIZZLECOMPONENT_ZERO: return stream << "ZERO";
238 case TEXTURESWIZZLECOMPONENT_ONE: return stream << "ONE";
239 default: DE_ASSERT(false); return stream;
243 struct MaybeTextureSwizzle
246 static MaybeTextureSwizzle createNoneTextureSwizzle (void);
247 static MaybeTextureSwizzle createSomeTextureSwizzle (void);
249 bool isSome (void) const;
250 bool isNone (void) const;
251 bool isIdentitySwizzle (void) const;
253 tcu::Vector<TextureSwizzleComponent, 4>& getSwizzle (void);
254 const tcu::Vector<TextureSwizzleComponent, 4>& getSwizzle (void) const;
257 MaybeTextureSwizzle (void);
259 tcu::Vector<TextureSwizzleComponent, 4> m_swizzle;
263 static std::ostream& operator<< (std::ostream& stream, const MaybeTextureSwizzle& comp)
266 stream << "[default swizzle state]";
268 stream << "(" << comp.getSwizzle()[0]
269 << ", " << comp.getSwizzle()[1]
270 << ", " << comp.getSwizzle()[2]
271 << ", " << comp.getSwizzle()[3]
277 MaybeTextureSwizzle MaybeTextureSwizzle::createNoneTextureSwizzle (void)
279 MaybeTextureSwizzle swizzle;
281 swizzle.m_swizzle[0] = TEXTURESWIZZLECOMPONENT_LAST;
282 swizzle.m_swizzle[1] = TEXTURESWIZZLECOMPONENT_LAST;
283 swizzle.m_swizzle[2] = TEXTURESWIZZLECOMPONENT_LAST;
284 swizzle.m_swizzle[3] = TEXTURESWIZZLECOMPONENT_LAST;
285 swizzle.m_isSome = false;
290 MaybeTextureSwizzle MaybeTextureSwizzle::createSomeTextureSwizzle (void)
292 MaybeTextureSwizzle swizzle;
294 swizzle.m_swizzle[0] = TEXTURESWIZZLECOMPONENT_R;
295 swizzle.m_swizzle[1] = TEXTURESWIZZLECOMPONENT_G;
296 swizzle.m_swizzle[2] = TEXTURESWIZZLECOMPONENT_B;
297 swizzle.m_swizzle[3] = TEXTURESWIZZLECOMPONENT_A;
298 swizzle.m_isSome = true;
303 bool MaybeTextureSwizzle::isSome (void) const
308 bool MaybeTextureSwizzle::isNone (void) const
313 bool MaybeTextureSwizzle::isIdentitySwizzle (void) const
316 m_swizzle[0] == TEXTURESWIZZLECOMPONENT_R &&
317 m_swizzle[1] == TEXTURESWIZZLECOMPONENT_G &&
318 m_swizzle[2] == TEXTURESWIZZLECOMPONENT_B &&
319 m_swizzle[3] == TEXTURESWIZZLECOMPONENT_A;
322 tcu::Vector<TextureSwizzleComponent, 4>& MaybeTextureSwizzle::getSwizzle (void)
327 const tcu::Vector<TextureSwizzleComponent, 4>& MaybeTextureSwizzle::getSwizzle (void) const
332 MaybeTextureSwizzle::MaybeTextureSwizzle (void)
333 : m_swizzle (TEXTURESWIZZLECOMPONENT_LAST, TEXTURESWIZZLECOMPONENT_LAST, TEXTURESWIZZLECOMPONENT_LAST, TEXTURESWIZZLECOMPONENT_LAST)
338 static vk::VkComponentSwizzle getTextureSwizzleComponent (TextureSwizzleComponent c)
342 case TEXTURESWIZZLECOMPONENT_R: return vk::VK_COMPONENT_SWIZZLE_R;
343 case TEXTURESWIZZLECOMPONENT_G: return vk::VK_COMPONENT_SWIZZLE_G;
344 case TEXTURESWIZZLECOMPONENT_B: return vk::VK_COMPONENT_SWIZZLE_B;
345 case TEXTURESWIZZLECOMPONENT_A: return vk::VK_COMPONENT_SWIZZLE_A;
346 case TEXTURESWIZZLECOMPONENT_ZERO: return vk::VK_COMPONENT_SWIZZLE_ZERO;
347 case TEXTURESWIZZLECOMPONENT_ONE: return vk::VK_COMPONENT_SWIZZLE_ONE;
348 default: DE_ASSERT(false); return (vk::VkComponentSwizzle)0;
352 template <typename T>
353 static inline T swizzleColorChannel (const tcu::Vector<T, 4>& src, TextureSwizzleComponent swizzle)
357 case TEXTURESWIZZLECOMPONENT_R: return src[0];
358 case TEXTURESWIZZLECOMPONENT_G: return src[1];
359 case TEXTURESWIZZLECOMPONENT_B: return src[2];
360 case TEXTURESWIZZLECOMPONENT_A: return src[3];
361 case TEXTURESWIZZLECOMPONENT_ZERO: return (T)0;
362 case TEXTURESWIZZLECOMPONENT_ONE: return (T)1;
363 default: DE_ASSERT(false); return (T)-1;
367 template <typename T>
368 static inline tcu::Vector<T, 4> swizzleColor (const tcu::Vector<T, 4>& src, const MaybeTextureSwizzle& swizzle)
370 DE_ASSERT(swizzle.isSome());
372 tcu::Vector<T, 4> result;
373 for (int i = 0; i < 4; i++)
374 result[i] = swizzleColorChannel(src, swizzle.getSwizzle()[i]);
378 template <typename T>
379 static void swizzlePixels (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src, const MaybeTextureSwizzle& swizzle)
381 DE_ASSERT(dst.getWidth() == src.getWidth() &&
382 dst.getHeight() == src.getHeight() &&
383 dst.getDepth() == src.getDepth());
384 for (int z = 0; z < src.getDepth(); z++)
385 for (int y = 0; y < src.getHeight(); y++)
386 for (int x = 0; x < src.getWidth(); x++)
387 dst.setPixel(swizzleColor(src.getPixelT<T>(x, y, z), swizzle), x, y, z);
390 static void swizzlePixels (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src, const MaybeTextureSwizzle& swizzle)
392 if (isDepthFormat(dst.getFormat()))
393 DE_ASSERT(swizzle.isNone() || swizzle.isIdentitySwizzle());
395 if (swizzle.isNone() || swizzle.isIdentitySwizzle())
397 else if (isUnormFormatType(dst.getFormat().type))
398 swizzlePixels<float>(dst, src, swizzle);
399 else if (isUIntFormatType(dst.getFormat().type))
400 swizzlePixels<deUint32>(dst, src, swizzle);
401 else if (isSIntFormatType(dst.getFormat().type))
402 swizzlePixels<deInt32>(dst, src, swizzle);
407 static void swizzleTexture (tcu::Texture2D& dst, const tcu::Texture2D& src, const MaybeTextureSwizzle& swizzle)
409 dst = tcu::Texture2D(src.getFormat(), src.getWidth(), src.getHeight());
410 for (int levelNdx = 0; levelNdx < src.getNumLevels(); levelNdx++)
412 if (src.isLevelEmpty(levelNdx))
414 dst.allocLevel(levelNdx);
415 swizzlePixels(dst.getLevel(levelNdx), src.getLevel(levelNdx), swizzle);
419 static void swizzleTexture (tcu::Texture2DArray& dst, const tcu::Texture2DArray& src, const MaybeTextureSwizzle& swizzle)
421 dst = tcu::Texture2DArray(src.getFormat(), src.getWidth(), src.getHeight(), src.getNumLayers());
422 for (int levelNdx = 0; levelNdx < src.getNumLevels(); levelNdx++)
424 if (src.isLevelEmpty(levelNdx))
426 dst.allocLevel(levelNdx);
427 swizzlePixels(dst.getLevel(levelNdx), src.getLevel(levelNdx), swizzle);
431 static void swizzleTexture (tcu::TextureCube& dst, const tcu::TextureCube& src, const MaybeTextureSwizzle& swizzle)
433 dst = tcu::TextureCube(src.getFormat(), src.getSize());
434 for (int faceI = 0; faceI < tcu::CUBEFACE_LAST; faceI++)
436 const tcu::CubeFace face = (tcu::CubeFace)faceI;
437 for (int levelNdx = 0; levelNdx < src.getNumLevels(); levelNdx++)
439 if (src.isLevelEmpty(face, levelNdx))
441 dst.allocLevel(face, levelNdx);
442 swizzlePixels(dst.getLevelFace(levelNdx, face), src.getLevelFace(levelNdx, face), swizzle);
447 static tcu::Texture2DView getOneLevelSubView (const tcu::Texture2DView& view, int level)
449 return tcu::Texture2DView(1, view.getLevels() + level);
452 static tcu::Texture2DArrayView getOneLevelSubView (const tcu::Texture2DArrayView& view, int level)
454 return tcu::Texture2DArrayView(1, view.getLevels() + level);
457 static tcu::TextureCubeView getOneLevelSubView (const tcu::TextureCubeView& view, int level)
459 const tcu::ConstPixelBufferAccess* levels[tcu::CUBEFACE_LAST];
461 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
462 levels[face] = view.getFaceLevels((tcu::CubeFace)face) + level;
464 return tcu::TextureCubeView(1, levels);
470 virtual void operator() (const IVec2& pixCoord, IVec2 (&dst)[4]) const = 0;
471 virtual ~PixelOffsets (void) {}
474 class MultiplePixelOffsets : public PixelOffsets
477 MultiplePixelOffsets (const IVec2& a,
488 void operator() (const IVec2& /* pixCoord */, IVec2 (&dst)[4]) const
490 for (int i = 0; i < DE_LENGTH_OF_ARRAY(dst); i++)
491 dst[i] = m_offsets[i];
498 class SinglePixelOffsets : public MultiplePixelOffsets
501 SinglePixelOffsets (const IVec2& offset)
502 : MultiplePixelOffsets(offset + IVec2(0, 1),
503 offset + IVec2(1, 1),
504 offset + IVec2(1, 0),
505 offset + IVec2(0, 0))
510 class DynamicSinglePixelOffsets : public PixelOffsets
513 DynamicSinglePixelOffsets (const IVec2& offsetRange) : m_offsetRange(offsetRange) {}
515 void operator() (const IVec2& pixCoord, IVec2 (&dst)[4]) const
517 const int offsetRangeSize = m_offsetRange.y() - m_offsetRange.x() + 1;
518 SinglePixelOffsets(tcu::mod(pixCoord.swizzle(1,0), IVec2(offsetRangeSize)) + m_offsetRange.x())(IVec2(), dst);
525 template <typename T>
526 static inline T triQuadInterpolate (const T (&values)[4], float xFactor, float yFactor)
528 if (xFactor + yFactor < 1.0f)
529 return values[0] + (values[2]-values[0])*xFactor + (values[1]-values[0])*yFactor;
531 return values[3] + (values[1]-values[3])*(1.0f-xFactor) + (values[2]-values[3])*(1.0f-yFactor);
535 static inline void computeTexCoordVecs (const vector<float>& texCoords, tcu::Vector<float, N> (&dst)[4])
537 DE_ASSERT((int)texCoords.size() == 4*N);
538 for (int i = 0; i < 4; i++)
539 for (int j = 0; j < N; j++)
540 dst[i][j] = texCoords[i*N + j];
543 #if defined(DE_DEBUG)
544 // Whether offsets correspond to the sample offsets used with plain textureGather().
545 static inline bool isZeroOffsetOffsets (const IVec2 (&offsets)[4])
548 SinglePixelOffsets(IVec2(0))(IVec2(), ref);
549 return std::equal(DE_ARRAY_BEGIN(offsets),
550 DE_ARRAY_END(offsets),
551 DE_ARRAY_BEGIN(ref));
555 template <typename ColorScalarType>
556 static tcu::Vector<ColorScalarType, 4> gatherOffsets (const tcu::Texture2DView& texture, const tcu::Sampler& sampler, const Vec2& coord, int componentNdx, const IVec2 (&offsets)[4])
558 return texture.gatherOffsets(sampler, coord.x(), coord.y(), componentNdx, offsets).cast<ColorScalarType>();
561 template <typename ColorScalarType>
562 static tcu::Vector<ColorScalarType, 4> gatherOffsets (const tcu::Texture2DArrayView& texture, const tcu::Sampler& sampler, const Vec3& coord, int componentNdx, const IVec2 (&offsets)[4])
564 return texture.gatherOffsets(sampler, coord.x(), coord.y(), coord.z(), componentNdx, offsets).cast<ColorScalarType>();
567 template <typename ColorScalarType>
568 static tcu::Vector<ColorScalarType, 4> gatherOffsets (const tcu::TextureCubeView& texture, const tcu::Sampler& sampler, const Vec3& coord, int componentNdx, const IVec2 (&offsets)[4])
570 DE_ASSERT(isZeroOffsetOffsets(offsets));
572 return texture.gather(sampler, coord.x(), coord.y(), coord.z(), componentNdx).cast<ColorScalarType>();
575 static Vec4 gatherOffsetsCompare (const tcu::Texture2DView& texture, const tcu::Sampler& sampler, float refZ, const Vec2& coord, const IVec2 (&offsets)[4])
577 return texture.gatherOffsetsCompare(sampler, refZ, coord.x(), coord.y(), offsets);
580 static Vec4 gatherOffsetsCompare (const tcu::Texture2DArrayView& texture, const tcu::Sampler& sampler, float refZ, const Vec3& coord, const IVec2 (&offsets)[4])
582 return texture.gatherOffsetsCompare(sampler, refZ, coord.x(), coord.y(), coord.z(), offsets);
585 static Vec4 gatherOffsetsCompare (const tcu::TextureCubeView& texture, const tcu::Sampler& sampler, float refZ, const Vec3& coord, const IVec2 (&offsets)[4])
587 DE_ASSERT(isZeroOffsetOffsets(offsets));
589 return texture.gatherCompare(sampler, refZ, coord.x(), coord.y(), coord.z());
592 template <typename PrecType, typename ColorScalarT>
593 static bool isGatherOffsetsResultValid (const tcu::TextureCubeView& texture,
594 const tcu::Sampler& sampler,
595 const PrecType& prec,
598 const IVec2 (&offsets)[4],
599 const tcu::Vector<ColorScalarT, 4>& result)
601 DE_ASSERT(isZeroOffsetOffsets(offsets));
603 return tcu::isGatherResultValid(texture, sampler, prec, coord, componentNdx, result);
606 static bool isGatherOffsetsCompareResultValid (const tcu::TextureCubeView& texture,
607 const tcu::Sampler& sampler,
608 const tcu::TexComparePrecision& prec,
610 const IVec2 (&offsets)[4],
614 DE_ASSERT(isZeroOffsetOffsets(offsets));
616 return tcu::isGatherCompareResultValid(texture, sampler, prec, coord, cmpReference, result);
619 template <typename ColorScalarType, typename PrecType, typename TexViewT, typename TexCoordT>
620 static bool verifyGatherOffsets (TestLog& log,
621 const ConstPixelBufferAccess& result,
622 const TexViewT& texture,
623 const TexCoordT (&texCoords)[4],
624 const tcu::Sampler& sampler,
625 const PrecType& lookupPrec,
627 const PixelOffsets& getPixelOffsets)
629 typedef tcu::Vector<ColorScalarType, 4> ColorVec;
631 const int width = result.getWidth();
632 const int height = result.getWidth();
633 tcu::TextureLevel ideal (result.getFormat(), width, height);
634 const PixelBufferAccess idealAccess = ideal.getAccess();
635 tcu::Surface errorMask (width, height);
638 tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec());
640 for (int py = 0; py < height; py++)
641 for (int px = 0; px < width; px++)
644 getPixelOffsets(IVec2(px, py), offsets);
646 const Vec2 viewportCoord = (Vec2((float)px, (float)py) + 0.5f) / Vec2((float)width, (float)height);
647 const TexCoordT texCoord = triQuadInterpolate(texCoords, viewportCoord.x(), viewportCoord.y());
648 const ColorVec resultPix = result.getPixelT<ColorScalarType>(px, py);
649 const ColorVec idealPix = gatherOffsets<ColorScalarType>(texture, sampler, texCoord, componentNdx, offsets);
651 idealAccess.setPixel(idealPix, px, py);
653 if (tcu::boolAny(tcu::logicalAnd(lookupPrec.colorMask,
654 tcu::greaterThan(tcu::absDiff(resultPix, idealPix),
655 lookupPrec.colorThreshold.template cast<ColorScalarType>()))))
657 if (!isGatherOffsetsResultValid(texture, sampler, lookupPrec, texCoord, componentNdx, offsets, resultPix))
659 errorMask.setPixel(px, py, tcu::RGBA::red());
665 log << TestLog::ImageSet("VerifyResult", "Verification result")
666 << TestLog::Image("Rendered", "Rendered image", result);
670 log << TestLog::Image("Reference", "Ideal reference image", ideal)
671 << TestLog::Image("ErrorMask", "Error mask", errorMask);
674 log << TestLog::EndImageSet;
679 class PixelCompareRefZ
682 virtual float operator() (const IVec2& pixCoord) const = 0;
685 class PixelCompareRefZDefault : public PixelCompareRefZ
688 PixelCompareRefZDefault (const IVec2& renderSize) : m_renderSize(renderSize) {}
690 float operator() (const IVec2& pixCoord) const
692 return ((float)pixCoord.x() + 0.5f) / (float)m_renderSize.x();
699 template <typename TexViewT, typename TexCoordT>
700 static bool verifyGatherOffsetsCompare (TestLog& log,
701 const ConstPixelBufferAccess& result,
702 const TexViewT& texture,
703 const TexCoordT (&texCoords)[4],
704 const tcu::Sampler& sampler,
705 const tcu::TexComparePrecision& compPrec,
706 const PixelCompareRefZ& getPixelRefZ,
707 const PixelOffsets& getPixelOffsets)
709 const int width = result.getWidth();
710 const int height = result.getWidth();
711 tcu::Surface ideal (width, height);
712 const PixelBufferAccess idealAccess = ideal.getAccess();
713 tcu::Surface errorMask (width, height);
716 tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec());
718 for (int py = 0; py < height; py++)
719 for (int px = 0; px < width; px++)
722 getPixelOffsets(IVec2(px, py), offsets);
724 const Vec2 viewportCoord = (Vec2((float)px, (float)py) + 0.5f) / Vec2((float)width, (float)height);
725 const TexCoordT texCoord = triQuadInterpolate(texCoords, viewportCoord.x(), viewportCoord.y());
726 const float refZ = getPixelRefZ(IVec2(px, py));
727 const Vec4 resultPix = result.getPixel(px, py);
728 const Vec4 idealPix = gatherOffsetsCompare(texture, sampler, refZ, texCoord, offsets);
730 idealAccess.setPixel(idealPix, px, py);
732 if (!tcu::boolAll(tcu::equal(resultPix, idealPix)))
734 if (!isGatherOffsetsCompareResultValid(texture, sampler, compPrec, texCoord, offsets, refZ, resultPix))
736 errorMask.setPixel(px, py, tcu::RGBA::red());
742 log << TestLog::ImageSet("VerifyResult", "Verification result")
743 << TestLog::Image("Rendered", "Rendered image", result);
747 log << TestLog::Image("Reference", "Ideal reference image", ideal)
748 << TestLog::Image("ErrorMask", "Error mask", errorMask);
751 log << TestLog::EndImageSet;
758 GATHERTYPE_BASIC = 0,
760 GATHERTYPE_OFFSET_DYNAMIC,
768 GATHERCASE_DONT_SAMPLE_CUBE_CORNERS = (1<<0) //!< For cube map cases: do not sample cube corners
774 OFFSETSIZE_MINIMUM_REQUIRED,
775 OFFSETSIZE_IMPLEMENTATION_MAXIMUM,
780 static inline const char* gatherTypeName (GatherType type)
784 case GATHERTYPE_BASIC: return "basic";
785 case GATHERTYPE_OFFSET: return "offset";
786 case GATHERTYPE_OFFSET_DYNAMIC: return "offset_dynamic";
787 case GATHERTYPE_OFFSETS: return "offsets";
788 default: DE_ASSERT(false); return DE_NULL;
792 static inline const char* gatherTypeDescription (GatherType type)
796 case GATHERTYPE_BASIC: return "textureGather";
797 case GATHERTYPE_OFFSET: return "textureGatherOffset";
798 case GATHERTYPE_OFFSET_DYNAMIC: return "textureGatherOffset with dynamic offsets";
799 case GATHERTYPE_OFFSETS: return "textureGatherOffsets";
800 default: DE_ASSERT(false); return DE_NULL;
804 static inline bool requireGpuShader5 (GatherType gatherType, OffsetSize offsetSize)
806 return gatherType == GATHERTYPE_OFFSET_DYNAMIC || gatherType == GATHERTYPE_OFFSETS
807 || offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM; // \note Implementation limits are not available while generating the shaders, they are passed dynamically at runtime
812 int componentNdx; // If negative, implicit component index 0 is used (i.e. the parameter is not given).
813 IVec2 offsets[4]; // \note Unless GATHERTYPE_OFFSETS is used, only offsets[0] is relevant; also, for GATHERTYPE_OFFSET_DYNAMIC, none are relevant.
818 std::fill(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), IVec2());
821 GatherArgs (int comp,
822 const IVec2& off0 = IVec2(),
823 const IVec2& off1 = IVec2(),
824 const IVec2& off2 = IVec2(),
825 const IVec2& off3 = IVec2())
835 static MovePtr<PixelOffsets> makePixelOffsetsFunctor (GatherType gatherType, const GatherArgs& gatherArgs, const IVec2& offsetRange)
837 if (gatherType == GATHERTYPE_BASIC || gatherType == GATHERTYPE_OFFSET)
839 const IVec2 offset = gatherType == GATHERTYPE_BASIC ? IVec2(0) : gatherArgs.offsets[0];
840 return MovePtr<PixelOffsets>(new SinglePixelOffsets(offset));
842 else if (gatherType == GATHERTYPE_OFFSET_DYNAMIC)
844 return MovePtr<PixelOffsets>(new DynamicSinglePixelOffsets(offsetRange));
846 else if (gatherType == GATHERTYPE_OFFSETS)
847 return MovePtr<PixelOffsets>(new MultiplePixelOffsets(gatherArgs.offsets[0],
848 gatherArgs.offsets[1],
849 gatherArgs.offsets[2],
850 gatherArgs.offsets[3]));
854 return MovePtr<PixelOffsets>(DE_NULL);
858 static inline glu::DataType getSamplerType (TextureType textureType, const tcu::TextureFormat& format)
860 if (isDepthFormat(format))
864 case TEXTURETYPE_2D: return glu::TYPE_SAMPLER_2D_SHADOW;
865 case TEXTURETYPE_2D_ARRAY: return glu::TYPE_SAMPLER_2D_ARRAY_SHADOW;
866 case TEXTURETYPE_CUBE: return glu::TYPE_SAMPLER_CUBE_SHADOW;
867 default: DE_ASSERT(false); return glu::TYPE_LAST;
874 case TEXTURETYPE_2D: return glu::getSampler2DType(format);
875 case TEXTURETYPE_2D_ARRAY: return glu::getSampler2DArrayType(format);
876 case TEXTURETYPE_CUBE: return glu::getSamplerCubeType(format);
877 default: DE_ASSERT(false); return glu::TYPE_LAST;
882 static inline glu::DataType getSamplerGatherResultType (glu::DataType samplerType)
886 case glu::TYPE_SAMPLER_2D_SHADOW:
887 case glu::TYPE_SAMPLER_2D_ARRAY_SHADOW:
888 case glu::TYPE_SAMPLER_CUBE_SHADOW:
889 case glu::TYPE_SAMPLER_2D:
890 case glu::TYPE_SAMPLER_2D_ARRAY:
891 case glu::TYPE_SAMPLER_CUBE:
892 return glu::TYPE_FLOAT_VEC4;
894 case glu::TYPE_INT_SAMPLER_2D:
895 case glu::TYPE_INT_SAMPLER_2D_ARRAY:
896 case glu::TYPE_INT_SAMPLER_CUBE:
897 return glu::TYPE_INT_VEC4;
899 case glu::TYPE_UINT_SAMPLER_2D:
900 case glu::TYPE_UINT_SAMPLER_2D_ARRAY:
901 case glu::TYPE_UINT_SAMPLER_CUBE:
902 return glu::TYPE_UINT_VEC4;
906 return glu::TYPE_LAST;
910 static inline int getNumTextureSamplingDimensions (TextureType type)
914 case TEXTURETYPE_2D: return 2;
915 case TEXTURETYPE_2D_ARRAY: return 3;
916 case TEXTURETYPE_CUBE: return 3;
917 default: DE_ASSERT(false); return -1;
928 vector<GatherArgs> generateBasic2DCaseIterations (GatherType gatherType, LevelMode levelMode, const tcu::TextureFormat& textureFormat, const IVec2& offsetRange)
930 const int numComponentCases = isDepthFormat(textureFormat) ? 1 : 4+1; // \note For non-depth textures, test explicit components 0 to 3 and implicit component 0.
931 const bool skipImplicitCase = (levelMode == LevelMode::AMD_BIAS);
932 vector<GatherArgs> result;
934 for (int componentCaseNdx = (skipImplicitCase ? 1 : 0); componentCaseNdx < numComponentCases; componentCaseNdx++)
936 const int componentNdx = componentCaseNdx - 1;
940 case GATHERTYPE_BASIC:
941 result.push_back(GatherArgs(componentNdx));
944 case GATHERTYPE_OFFSET:
946 const int min = offsetRange.x();
947 const int max = offsetRange.y();
948 const int hmin = divRoundToZero(min, 2);
949 const int hmax = divRoundToZero(max, 2);
951 result.push_back(GatherArgs(componentNdx, IVec2(min, max)));
953 if (componentCaseNdx == 0) // Don't test all offsets variants for all color components (they should be pretty orthogonal).
955 result.push_back(GatherArgs(componentNdx, IVec2(min, min)));
956 result.push_back(GatherArgs(componentNdx, IVec2(max, min)));
957 result.push_back(GatherArgs(componentNdx, IVec2(max, max)));
959 result.push_back(GatherArgs(componentNdx, IVec2(0, hmax)));
960 result.push_back(GatherArgs(componentNdx, IVec2(hmin, 0)));
961 result.push_back(GatherArgs(componentNdx, IVec2(0, 0)));
967 case GATHERTYPE_OFFSET_DYNAMIC:
968 result.push_back(GatherArgs(componentNdx));
971 case GATHERTYPE_OFFSETS:
973 const int min = offsetRange.x();
974 const int max = offsetRange.y();
975 const int hmin = divRoundToZero(min, 2);
976 const int hmax = divRoundToZero(max, 2);
978 result.push_back(GatherArgs(componentNdx,
984 if (componentCaseNdx == 0) // Don't test all offsets variants for all color components (they should be pretty orthogonal).
985 result.push_back(GatherArgs(componentNdx,
1001 struct GatherCaseBaseParams
1003 GatherType gatherType;
1004 OffsetSize offsetSize;
1005 tcu::TextureFormat textureFormat;
1006 tcu::Sampler::CompareMode shadowCompareMode;
1007 tcu::Sampler::WrapMode wrapS;
1008 tcu::Sampler::WrapMode wrapT;
1009 MaybeTextureSwizzle textureSwizzle;
1010 tcu::Sampler::FilterMode minFilter;
1011 tcu::Sampler::FilterMode magFilter;
1012 LevelMode levelMode;
1015 TextureType textureType;
1016 ImageBackingMode sparseCase;
1018 GatherCaseBaseParams (const TextureType textureType_,
1019 const GatherType gatherType_,
1020 const OffsetSize offsetSize_,
1021 const tcu::TextureFormat textureFormat_,
1022 const tcu::Sampler::CompareMode shadowCompareMode_,
1023 const tcu::Sampler::WrapMode wrapS_,
1024 const tcu::Sampler::WrapMode wrapT_,
1025 const MaybeTextureSwizzle& textureSwizzle_,
1026 const tcu::Sampler::FilterMode minFilter_,
1027 const tcu::Sampler::FilterMode magFilter_,
1028 const LevelMode levelMode_,
1029 const int baseLevel_,
1030 const deUint32 flags_,
1031 const ImageBackingMode sparseCase_)
1032 : gatherType (gatherType_)
1033 , offsetSize (offsetSize_)
1034 , textureFormat (textureFormat_)
1035 , shadowCompareMode (shadowCompareMode_)
1038 , textureSwizzle (textureSwizzle_)
1039 , minFilter (minFilter_)
1040 , magFilter (magFilter_)
1041 , levelMode (levelMode_)
1042 , baseLevel (baseLevel_)
1044 , textureType (textureType_)
1045 , sparseCase (sparseCase_)
1048 GatherCaseBaseParams (void)
1049 : gatherType (GATHERTYPE_LAST)
1050 , offsetSize (OFFSETSIZE_LAST)
1052 , shadowCompareMode (tcu::Sampler::COMPAREMODE_LAST)
1053 , wrapS (tcu::Sampler::WRAPMODE_LAST)
1054 , wrapT (tcu::Sampler::WRAPMODE_LAST)
1055 , textureSwizzle (MaybeTextureSwizzle::createNoneTextureSwizzle())
1056 , minFilter (tcu::Sampler::FILTERMODE_LAST)
1057 , magFilter (tcu::Sampler::FILTERMODE_LAST)
1058 , levelMode (LevelMode::NORMAL)
1061 , textureType (TEXTURETYPE_LAST)
1062 , sparseCase (ShaderRenderCaseInstance::IMAGE_BACKING_MODE_REGULAR)
1066 static void checkMutableComparisonSamplersSupport(Context& context, const GatherCaseBaseParams& m_baseParams)
1068 // when compare mode is not none then ShaderRenderCaseInstance::createSamplerUniform
1069 // uses mapSampler utill from vkImageUtil that sets compareEnable to true
1070 // for portability this needs to be under feature flag
1071 #ifndef CTS_USES_VULKANSC
1072 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
1073 !context.getPortabilitySubsetFeatures().mutableComparisonSamplers &&
1074 (m_baseParams.shadowCompareMode != tcu::Sampler::COMPAREMODE_NONE))
1076 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: mutableComparisonSamplers are not supported by this implementation");
1080 DE_UNREF(m_baseParams);
1081 #endif // CTS_USES_VULKANSC
1084 IVec2 getOffsetRange (const OffsetSize offsetSize, const vk::VkPhysicalDeviceLimits& deviceLimits)
1088 case OFFSETSIZE_NONE:
1091 case OFFSETSIZE_MINIMUM_REQUIRED:
1092 // \note Defined by spec.
1093 return IVec2(SPEC_MAX_MIN_OFFSET,
1094 SPEC_MIN_MAX_OFFSET);
1096 case OFFSETSIZE_IMPLEMENTATION_MAXIMUM:
1097 return IVec2(deviceLimits.minTexelGatherOffset, deviceLimits.maxTexelGatherOffset);
1105 IVec2 getOffsetRange (const OffsetSize offsetSize)
1109 case OFFSETSIZE_NONE:
1112 case OFFSETSIZE_MINIMUM_REQUIRED:
1113 // \note Defined by spec.
1114 return IVec2(SPEC_MAX_MIN_OFFSET,
1115 SPEC_MIN_MAX_OFFSET);
1117 case OFFSETSIZE_IMPLEMENTATION_MAXIMUM:
1118 DE_FATAL("Not known");
1127 class TextureGatherInstance : public ShaderRenderCaseInstance
1130 TextureGatherInstance (Context& context,
1131 const GatherCaseBaseParams& baseParams);
1132 virtual ~TextureGatherInstance (void);
1134 virtual tcu::TestStatus iterate (void);
1139 virtual int getNumIterations (void) const = 0;
1140 virtual GatherArgs getGatherArgs (int iterationNdx) const = 0;
1142 virtual void setupDefaultInputs (void);
1143 virtual void setupUniforms (const tcu::Vec4&);
1145 template <typename TexViewT, typename TexCoordT>
1146 bool verify (const ConstPixelBufferAccess& rendered,
1147 const TexViewT& texture,
1148 const TexCoordT (&bottomLeft)[4],
1149 const GatherArgs& gatherArgs) const;
1151 virtual TextureBindingSp createTexture (void) = 0;
1152 virtual vector<float> computeQuadTexCoord (int iterationNdx) const = 0;
1153 virtual bool verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const = 0;
1156 static const IVec2 RENDER_SIZE;
1158 const GatherCaseBaseParams m_baseParams;
1161 const tcu::TextureFormat m_colorBufferFormat;
1162 int m_currentIteration;
1165 const IVec2 TextureGatherInstance::RENDER_SIZE = IVec2(64, 64);
1167 TextureGatherInstance::TextureGatherInstance (Context& context,
1168 const GatherCaseBaseParams& baseParams)
1169 : ShaderRenderCaseInstance (context, false, DE_NULL, DE_NULL, DE_NULL, baseParams.sparseCase)
1170 , m_baseParams (baseParams)
1171 , m_colorBufferFormat (tcu::TextureFormat(tcu::TextureFormat::RGBA,
1172 isDepthFormat(baseParams.textureFormat) ? tcu::TextureFormat::UNORM_INT8 : baseParams.textureFormat.type))
1173 , m_currentIteration (0)
1175 DE_ASSERT((m_baseParams.gatherType == GATHERTYPE_BASIC) == (m_baseParams.offsetSize == OFFSETSIZE_NONE));
1176 DE_ASSERT((m_baseParams.shadowCompareMode != tcu::Sampler::COMPAREMODE_NONE) == isDepthFormat(m_baseParams.textureFormat));
1177 DE_ASSERT(isUnormFormatType(m_colorBufferFormat.type) ||
1178 m_colorBufferFormat.type == tcu::TextureFormat::UNSIGNED_INT8 ||
1179 m_colorBufferFormat.type == tcu::TextureFormat::UNSIGNED_INT16 ||
1180 m_colorBufferFormat.type == tcu::TextureFormat::SIGNED_INT8 ||
1181 m_colorBufferFormat.type == tcu::TextureFormat::SIGNED_INT16);
1182 DE_ASSERT(glu::isGLInternalColorFormatFilterable(glu::getInternalFormat(m_colorBufferFormat)) ||
1183 (m_baseParams.magFilter == tcu::Sampler::NEAREST && (m_baseParams.minFilter == tcu::Sampler::NEAREST || m_baseParams.minFilter == tcu::Sampler::NEAREST_MIPMAP_NEAREST)));
1184 DE_ASSERT(m_baseParams.textureType == TEXTURETYPE_CUBE || !(m_baseParams.flags & GATHERCASE_DONT_SAMPLE_CUBE_CORNERS));
1186 m_renderSize = RENDER_SIZE.asUint();
1187 m_colorFormat = vk::mapTextureFormat(m_colorBufferFormat);
1189 #ifdef CTS_USES_VULKANSC
1190 const VkDevice vkDevice = getDevice();
1191 const DeviceInterface& vk = getDeviceInterface();
1192 const deUint32 queueFamilyIndex = getUniversalQueueFamilyIndex();
1193 m_externalCommandPool = de::SharedPtr<Unique<VkCommandPool>>(new vk::Unique<VkCommandPool>(createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex)));
1194 #endif // CTS_USES_VULKANSC
1197 TextureGatherInstance::~TextureGatherInstance (void)
1201 void TextureGatherInstance::init (void)
1203 TestLog& log = m_context.getTestContext().getLog();
1204 TextureBindingSp textureBinding;
1205 TextureBinding::Parameters textureParams;
1207 // Check prerequisites.
1208 if (requireGpuShader5(m_baseParams.gatherType, m_baseParams.offsetSize))
1210 const vk::VkPhysicalDeviceFeatures& deviceFeatures = m_context.getDeviceFeatures();
1211 if (!deviceFeatures.shaderImageGatherExtended)
1212 TCU_THROW(NotSupportedError, "Extended set of image gather instructions are not supported");
1215 // Check general extension support.
1216 if (m_baseParams.levelMode != LevelMode::NORMAL)
1218 m_context.requireDeviceFunctionality("VK_AMD_texture_gather_bias_lod");
1221 // Log and check implementation offset limits, if appropriate.
1222 if (m_baseParams.offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
1224 const IVec2 offsetRange = getOffsetRange(m_baseParams.offsetSize, m_context.getDeviceProperties().limits);
1225 log << TestLog::Integer("ImplementationMinTextureGatherOffset", "Implementation's value for minTexelGatherOffset", "", QP_KEY_TAG_NONE, offsetRange[0])
1226 << TestLog::Integer("ImplementationMaxTextureGatherOffset", "Implementation's value for maxTexelGatherOffset", "", QP_KEY_TAG_NONE, offsetRange[1]);
1227 TCU_CHECK_MSG(offsetRange[0] <= SPEC_MAX_MIN_OFFSET, ("minTexelGatherOffset must be at most " + de::toString((int)SPEC_MAX_MIN_OFFSET)).c_str());
1228 TCU_CHECK_MSG(offsetRange[1] >= SPEC_MIN_MAX_OFFSET, ("maxTexelGatherOffset must be at least " + de::toString((int)SPEC_MIN_MAX_OFFSET)).c_str());
1231 // Initialize texture.
1232 textureBinding = createTexture();
1234 // Check image format support.
1235 // This should happen earlier but it's easier to retrieve texture parameters once created and this is not expected to fail.
1236 #ifndef CTS_USES_VULKANSC
1237 if (m_baseParams.levelMode != LevelMode::NORMAL)
1239 const auto format = vk::mapTextureFormat(m_baseParams.textureFormat);
1240 const auto bindingType = textureBinding->getType();
1241 const auto imageViewType = textureTypeToImageViewType(bindingType);
1242 const auto imageType = viewTypeToImageType(imageViewType);
1243 const vk::VkImageUsageFlags usageFlags = textureUsageFlags();
1244 const vk::VkImageCreateFlags imageCreateFlags = textureCreateFlags(imageViewType, m_baseParams.sparseCase);
1246 const vk::VkPhysicalDeviceImageFormatInfo2 formatInfo =
1248 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // VkStructureType sType;
1249 nullptr, // const void* pNext;
1250 format, // VkFormat format;
1251 imageType, // VkImageType type;
1252 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1253 usageFlags, // VkImageUsageFlags usage;
1254 imageCreateFlags, // VkImageCreateFlags flags;
1257 vk::VkTextureLODGatherFormatPropertiesAMD lodGatherProperties =
1259 vk::VK_STRUCTURE_TYPE_TEXTURE_LOD_GATHER_FORMAT_PROPERTIES_AMD, // VkStructureType sType;
1260 nullptr, // void* pNext;
1261 VK_FALSE, // VkBool32 supportsTextureGatherLODBiasAMD;
1264 vk::VkImageFormatProperties2 properties2 = vk::initVulkanStructure();
1265 properties2.pNext = &lodGatherProperties;
1267 const auto retCode = m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties2(m_context.getPhysicalDevice(), &formatInfo, &properties2);
1269 if (retCode != vk::VK_SUCCESS && retCode != vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
1270 TCU_FAIL("vkGetPhysicalDeviceImageFormatProperties2 returned " + de::toString(retCode));
1272 if (retCode == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
1273 TCU_THROW(NotSupportedError, "Format does not support the required parameters");
1275 if (!lodGatherProperties.supportsTextureGatherLODBiasAMD)
1276 TCU_THROW(NotSupportedError, "Format does not support texture gather LOD/Bias operations");
1280 if (m_baseParams.textureSwizzle.isSome())
1282 const tcu::Vector<TextureSwizzleComponent, 4>& swizzle = m_baseParams.textureSwizzle.getSwizzle();
1284 const vk::VkComponentMapping components =
1286 getTextureSwizzleComponent(swizzle[0]),
1287 getTextureSwizzleComponent(swizzle[1]),
1288 getTextureSwizzleComponent(swizzle[2]),
1289 getTextureSwizzleComponent(swizzle[3])
1292 textureParams.componentMapping = components;
1295 // Set base mip level and mode.
1296 if (m_baseParams.levelMode == LevelMode::NORMAL)
1298 textureParams.baseMipLevel = m_baseParams.baseLevel;
1302 const auto textureType = textureBinding->getType();
1305 switch (textureType)
1307 case TextureBinding::TYPE_1D: levels = textureBinding->get1D().getNumLevels(); break;
1308 case TextureBinding::TYPE_2D: levels = textureBinding->get2D().getNumLevels(); break;
1309 case TextureBinding::TYPE_3D: levels = textureBinding->get3D().getNumLevels(); break;
1310 case TextureBinding::TYPE_CUBE_MAP: levels = textureBinding->getCube().getNumLevels(); break;
1311 case TextureBinding::TYPE_1D_ARRAY: levels = textureBinding->get1DArray().getNumLevels(); break;
1312 case TextureBinding::TYPE_2D_ARRAY: levels = textureBinding->get2DArray().getNumLevels(); break;
1313 case TextureBinding::TYPE_CUBE_ARRAY: levels = textureBinding->getCubeArray().getNumLevels(); break;
1315 DE_ASSERT(false); break;
1318 DE_ASSERT(levels > 0);
1319 textureParams.minMaxLod = tcu::just(TextureBinding::MinMaxLod(0.0f, static_cast<float>(levels - 1)));
1322 textureBinding->setParameters(textureParams);
1323 m_textures.push_back(textureBinding);
1325 log << TestLog::Message << "Texture base level is " << textureParams.baseMipLevel << TestLog::EndMessage
1326 << TestLog::Message << "s and t wrap modes are "
1327 << vk::mapWrapMode(m_baseParams.wrapS) << " and "
1328 << vk::mapWrapMode(m_baseParams.wrapT) << ", respectively" << TestLog::EndMessage
1329 << TestLog::Message << "Minification and magnification filter modes are "
1330 << vk::mapFilterMode(m_baseParams.minFilter) << " and "
1331 << vk::mapFilterMode(m_baseParams.magFilter) << ", respectively "
1332 << "(note that they should have no effect on gather result)"
1333 << TestLog::EndMessage
1334 << TestLog::Message << "Using texture swizzle " << m_baseParams.textureSwizzle << TestLog::EndMessage;
1336 if (m_baseParams.shadowCompareMode != tcu::Sampler::COMPAREMODE_NONE)
1337 log << TestLog::Message << "Using texture compare func " << vk::mapCompareMode(m_baseParams.shadowCompareMode) << TestLog::EndMessage;
1340 void TextureGatherInstance::setupDefaultInputs (void)
1342 const int numVertices = 4;
1343 const float position[4*2] =
1350 const float normalizedCoord[4*2] =
1357 const vector<float> texCoord = computeQuadTexCoord(m_currentIteration);
1358 const bool needNormalizedCoordInShader = m_baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC || isDepthFormat(m_baseParams.textureFormat);
1360 addAttribute(0u, vk::VK_FORMAT_R32G32_SFLOAT, 2 * (deUint32)sizeof(float), numVertices, position);
1362 if (texCoord.size() == 2*4)
1363 addAttribute(1u, vk::VK_FORMAT_R32G32_SFLOAT, 2 * (deUint32)sizeof(float), numVertices, texCoord.data());
1364 else if (texCoord.size() == 3*4)
1365 addAttribute(1u, vk::VK_FORMAT_R32G32B32_SFLOAT, 3 * (deUint32)sizeof(float), numVertices, texCoord.data());
1369 if (needNormalizedCoordInShader)
1370 addAttribute(2u, vk::VK_FORMAT_R32G32_SFLOAT, 2 * (deUint32)sizeof(float), numVertices, normalizedCoord);
1373 tcu::TestStatus TextureGatherInstance::iterate (void)
1375 TestLog& log = m_context.getTestContext().getLog();
1376 const tcu::ScopedLogSection iterationSection (log, "Iteration" + de::toString(m_currentIteration), "Iteration " + de::toString(m_currentIteration));
1381 const deUint32 numVertices = 4;
1382 const deUint32 numTriangles = 2;
1383 const deUint16 indices[6] = { 0, 1, 2, 2, 1, 3 };
1384 const vector<float> texCoord = computeQuadTexCoord(m_currentIteration);
1386 if (texCoord.size() == 2*4)
1388 Vec2 texCoordVec[4];
1389 computeTexCoordVecs(texCoord, texCoordVec);
1390 log << TestLog::Message << "Texture coordinates run from " << texCoordVec[0] << " to " << texCoordVec[3] << TestLog::EndMessage;
1392 else if (texCoord.size() == 3*4)
1394 Vec3 texCoordVec[4];
1395 computeTexCoordVecs(texCoord, texCoordVec);
1396 log << TestLog::Message << "Texture coordinates run from " << texCoordVec[0] << " to " << texCoordVec[3] << TestLog::EndMessage;
1401 m_vertexShaderName = "vert";
1402 m_fragmentShaderName = "frag_" + de::toString(m_currentIteration);
1406 render(numVertices, numTriangles, indices);
1410 bool result = verify(m_currentIteration, getResultImage().getAccess());
1411 #ifdef CTS_USES_VULKANSC
1412 if (m_context.getTestContext().getCommandLine().isSubProcess())
1413 #endif // CTS_USES_VULKANSC
1416 return tcu::TestStatus::fail("Result verification failed");
1419 m_currentIteration++;
1420 if (m_currentIteration == getNumIterations())
1421 return tcu::TestStatus::pass("Pass");
1423 return tcu::TestStatus::incomplete();
1426 void TextureGatherInstance::setupUniforms (const tcu::Vec4&)
1428 deUint32 binding = 0;
1430 useSampler(binding++, 0u);
1432 if (m_baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC)
1433 addUniform(binding++, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::Vec2), RENDER_SIZE.asFloat().getPtr());
1435 if (m_baseParams.offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
1437 if (m_baseParams.gatherType == GATHERTYPE_OFFSET)
1439 const GatherArgs& gatherArgs = getGatherArgs(m_currentIteration);
1440 addUniform(binding++, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::IVec2), gatherArgs.offsets[0].getPtr());
1442 else if (m_baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC)
1444 const IVec2& offsetRange = getOffsetRange(m_baseParams.offsetSize, m_context.getDeviceProperties().limits);
1445 addUniform(binding++, vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, sizeof(tcu::IVec2), offsetRange.getPtr());
1452 template <typename TexViewT, typename TexCoordT>
1453 bool TextureGatherInstance::verify (const ConstPixelBufferAccess& rendered,
1454 const TexViewT& texture,
1455 const TexCoordT (&texCoords)[4],
1456 const GatherArgs& gatherArgs) const
1458 TestLog& log = m_context.getTestContext().getLog();
1461 DE_ASSERT(m_colorBufferFormat.order == tcu::TextureFormat::RGBA);
1462 DE_ASSERT(m_colorBufferFormat.type == tcu::TextureFormat::UNORM_INT8 ||
1463 m_colorBufferFormat.type == tcu::TextureFormat::UNSIGNED_INT8 ||
1464 m_colorBufferFormat.type == tcu::TextureFormat::SIGNED_INT8);
1466 const MovePtr<PixelOffsets> pixelOffsets = makePixelOffsetsFunctor(m_baseParams.gatherType, gatherArgs, getOffsetRange(m_baseParams.offsetSize, m_context.getDeviceProperties().limits));
1467 const tcu::PixelFormat pixelFormat = tcu::PixelFormat(8,8,8,8);
1468 const IVec4 colorBits = tcu::max(TextureTestUtil::getBitsVec(pixelFormat) - 1, tcu::IVec4(0));
1469 const IVec3 coordBits = m_baseParams.textureType == TEXTURETYPE_2D ? IVec3(20,20,0)
1470 : m_baseParams.textureType == TEXTURETYPE_CUBE ? IVec3(10,10,10)
1471 : m_baseParams.textureType == TEXTURETYPE_2D_ARRAY ? IVec3(20,20,20)
1473 const IVec3 uvwBits = m_baseParams.textureType == TEXTURETYPE_2D ? IVec3(7,7,0)
1474 : m_baseParams.textureType == TEXTURETYPE_CUBE ? IVec3(6,6,0)
1475 : m_baseParams.textureType == TEXTURETYPE_2D_ARRAY ? IVec3(7,7,7)
1477 tcu::Sampler sampler;
1478 sampler.wrapS = m_baseParams.wrapS;
1479 sampler.wrapT = m_baseParams.wrapT;
1480 sampler.compare = m_baseParams.shadowCompareMode;
1481 sampler.seamlessCubeMap = true;
1483 if (isDepthFormat(m_baseParams.textureFormat))
1485 tcu::TexComparePrecision comparePrec;
1486 comparePrec.coordBits = coordBits;
1487 comparePrec.uvwBits = uvwBits;
1488 comparePrec.referenceBits = 16;
1489 comparePrec.resultBits = pixelFormat.redBits-1;
1491 return verifyGatherOffsetsCompare(log, rendered, texture, texCoords, sampler, comparePrec, PixelCompareRefZDefault(RENDER_SIZE), *pixelOffsets);
1495 const int componentNdx = de::max(0, gatherArgs.componentNdx);
1497 if (isUnormFormatType(m_baseParams.textureFormat.type))
1499 tcu::LookupPrecision lookupPrec;
1500 lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(colorBits);
1501 lookupPrec.coordBits = coordBits;
1502 lookupPrec.uvwBits = uvwBits;
1503 lookupPrec.colorMask = TextureTestUtil::getCompareMask(pixelFormat);
1504 return verifyGatherOffsets<float>(log, rendered, texture, texCoords, sampler, lookupPrec, componentNdx, *pixelOffsets);
1506 else if (isUIntFormatType(m_baseParams.textureFormat.type) || isSIntFormatType(m_baseParams.textureFormat.type))
1508 tcu::IntLookupPrecision lookupPrec;
1509 lookupPrec.colorThreshold = UVec4(0);
1510 lookupPrec.coordBits = coordBits;
1511 lookupPrec.uvwBits = uvwBits;
1512 lookupPrec.colorMask = TextureTestUtil::getCompareMask(pixelFormat);
1514 if (isUIntFormatType(m_baseParams.textureFormat.type))
1515 return verifyGatherOffsets<deUint32>(log, rendered, texture, texCoords, sampler, lookupPrec, componentNdx, *pixelOffsets);
1516 else if (isSIntFormatType(m_baseParams.textureFormat.type))
1517 return verifyGatherOffsets<deInt32>(log, rendered, texture, texCoords, sampler, lookupPrec, componentNdx, *pixelOffsets);
1533 glu::VertexSource genVertexShaderSource (bool requireGpuShader5, int numTexCoordComponents, bool useNormalizedCoordInput)
1535 DE_ASSERT(numTexCoordComponents == 2 || numTexCoordComponents == 3);
1537 const string texCoordType = "vec" + de::toString(numTexCoordComponents);
1538 std::ostringstream vert;
1540 vert << "#version 310 es\n";
1542 if (requireGpuShader5)
1543 vert << "#extension GL_EXT_gpu_shader5 : require\n";
1546 "layout (location = 0) in highp vec2 a_position;\n"
1547 "layout (location = 1) in highp " << texCoordType << " a_texCoord;\n";
1549 if (useNormalizedCoordInput)
1550 vert << "layout (location = 2) in highp vec2 a_normalizedCoord; // (0,0) to (1,1)\n";
1553 "layout (location = 0) out highp " << texCoordType << " v_texCoord;\n";
1555 if (useNormalizedCoordInput)
1556 vert << "layout (location = 1) out highp vec2 v_normalizedCoord;\n";
1559 "void main (void)\n"
1561 " gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0);\n"
1562 " v_texCoord = a_texCoord;\n";
1564 if (useNormalizedCoordInput)
1565 vert << " v_normalizedCoord = a_normalizedCoord;\n";
1569 return glu::VertexSource(vert.str());
1572 glu::FragmentSource genFragmentShaderSource (bool requireGpuShader5,
1573 int numTexCoordComponents,
1574 glu::DataType samplerType,
1575 const string& funcCall,
1576 bool useNormalizedCoordInput,
1578 OffsetSize offsetSize,
1579 const ImageBackingMode sparseCase,
1580 LevelMode levelMode)
1582 DE_ASSERT(glu::isDataTypeSampler(samplerType));
1583 DE_ASSERT(de::inRange(numTexCoordComponents, 2, 3));
1584 DE_ASSERT(!usePixCoord || useNormalizedCoordInput);
1586 const string texCoordType = "vec" + de::toString(numTexCoordComponents);
1587 deUint32 binding = 0;
1588 std::ostringstream frag;
1589 const string outType = glu::getDataTypeName(getSamplerGatherResultType(samplerType));
1591 frag << "#version 450\n";
1593 if (sparseCase == ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE)
1594 frag << "#extension GL_ARB_sparse_texture2 : require\n";
1596 if (levelMode != LevelMode::NORMAL)
1597 frag << "#extension GL_AMD_texture_gather_bias_lod : require\n";
1599 if (requireGpuShader5)
1600 frag << "#extension GL_EXT_gpu_shader5 : require\n";
1603 "layout (location = 0) out mediump " << outType << " o_color;\n"
1605 "layout (location = 0) in highp " << texCoordType << " v_texCoord;\n";
1607 if (useNormalizedCoordInput)
1608 frag << "layout (location = 1) in highp vec2 v_normalizedCoord;\n";
1611 "layout (binding = " << binding++ << ") uniform highp " << glu::getDataTypeName(samplerType) << " u_sampler;\n";
1614 frag << "layout (binding = " << binding++ << ") uniform viewportSize { highp vec2 u_viewportSize; };\n";
1616 if (offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
1617 frag << "layout (binding = " << binding++ << ") uniform offset { highp ivec2 u_offset; };\n";
1624 frag << " ivec2 pixCoord = ivec2(v_normalizedCoord*u_viewportSize);\n";
1626 if (sparseCase == ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE)
1628 // Texel declaration
1629 frag << "\t" << outType << " texel;\n";
1630 frag << "\tint success = " << funcCall << ";\n";
1632 // Check sparse validity, and handle each case
1633 frag << "\tif (sparseTexelsResidentARB(success))\n"
1634 << "\t\to_color = texel;\n"
1636 << "\t\to_color = " << outType << "(0.0, 0.0, 0.0, 1.0);\n";
1640 frag << "\t\to_color = " << funcCall << ";\n";
1645 return glu::FragmentSource(frag.str());
1648 string genGatherFuncCall (GatherType gatherType,
1649 const tcu::TextureFormat& textureFormat,
1650 const GatherArgs& gatherArgs,
1651 LevelMode levelMode,
1653 const string& refZExpr,
1654 const IVec2& offsetRange,
1655 int indentationDepth,
1656 OffsetSize offsetSize,
1657 const ImageBackingMode sparseCase)
1662 if (levelMode != LevelMode::NORMAL)
1664 levelStr = de::toString(baseLevel) + ".0";
1667 if (sparseCase == ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE)
1669 if (levelMode == LevelMode::NORMAL || levelMode == LevelMode::AMD_BIAS)
1673 case GATHERTYPE_BASIC:
1674 result += "sparseTextureGatherARB";
1676 case GATHERTYPE_OFFSET: // \note Fallthrough.
1677 case GATHERTYPE_OFFSET_DYNAMIC:
1678 result += "sparseTextureGatherOffsetARB";
1680 case GATHERTYPE_OFFSETS:
1681 result += "sparseTextureGatherOffsetsARB";
1687 else // LevelMode::AMD_LOD
1691 case GATHERTYPE_BASIC:
1692 result += "sparseTextureGatherLodAMD";
1694 case GATHERTYPE_OFFSET: // \note Fallthrough.
1695 case GATHERTYPE_OFFSET_DYNAMIC:
1696 result += "sparseTextureGatherLodOffsetAMD";
1698 case GATHERTYPE_OFFSETS:
1699 result += "sparseTextureGatherLodOffsetsAMD";
1708 if (levelMode == LevelMode::NORMAL || levelMode == LevelMode::AMD_BIAS)
1712 case GATHERTYPE_BASIC:
1713 result += "textureGather";
1715 case GATHERTYPE_OFFSET: // \note Fallthrough.
1716 case GATHERTYPE_OFFSET_DYNAMIC:
1717 result += "textureGatherOffset";
1719 case GATHERTYPE_OFFSETS:
1720 result += "textureGatherOffsets";
1726 else // LevelMode::AMD_LOD
1730 case GATHERTYPE_BASIC:
1731 result += "textureGatherLodAMD";
1733 case GATHERTYPE_OFFSET: // \note Fallthrough.
1734 case GATHERTYPE_OFFSET_DYNAMIC:
1735 result += "textureGatherLodOffsetAMD";
1737 case GATHERTYPE_OFFSETS:
1738 result += "textureGatherLodOffsetsAMD";
1746 result += "(u_sampler, v_texCoord";
1748 if (isDepthFormat(textureFormat))
1750 DE_ASSERT(gatherArgs.componentNdx < 0);
1751 result += ", " + refZExpr;
1754 if (levelMode == LevelMode::AMD_LOD)
1756 result += ", " + levelStr;
1759 if (gatherType == GATHERTYPE_OFFSET ||
1760 gatherType == GATHERTYPE_OFFSET_DYNAMIC ||
1761 gatherType == GATHERTYPE_OFFSETS)
1766 case GATHERTYPE_OFFSET:
1767 if (offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
1768 result += "u_offset";
1770 result += "ivec2" + de::toString(gatherArgs.offsets[0]);
1773 case GATHERTYPE_OFFSET_DYNAMIC:
1774 if (offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM)
1775 result += "pixCoord.yx % ivec2(u_offset.y - u_offset.x + 1) + u_offset.x";
1777 result += "pixCoord.yx % ivec2(" + de::toString(offsetRange.y() - offsetRange.x() + 1) + ") + " + de::toString(offsetRange.x());
1780 case GATHERTYPE_OFFSETS:
1781 DE_ASSERT(offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM);
1782 result += "ivec2[4](\n"
1783 + string(indentationDepth, '\t') + "\tivec2" + de::toString(gatherArgs.offsets[0]) + ",\n"
1784 + string(indentationDepth, '\t') + "\tivec2" + de::toString(gatherArgs.offsets[1]) + ",\n"
1785 + string(indentationDepth, '\t') + "\tivec2" + de::toString(gatherArgs.offsets[2]) + ",\n"
1786 + string(indentationDepth, '\t') + "\tivec2" + de::toString(gatherArgs.offsets[3]) + ")\n"
1787 + string(indentationDepth, '\t') + "\t";
1795 if (sparseCase == ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE)
1796 result += ", texel";
1798 if (gatherArgs.componentNdx >= 0)
1800 DE_ASSERT(gatherArgs.componentNdx < 4);
1801 result += ", " + de::toString(gatherArgs.componentNdx);
1804 if (levelMode == LevelMode::AMD_BIAS)
1806 result += ", " + levelStr;
1814 // \todo [2016-07-08 pyry] Re-use programs if sources are identical
1816 void genGatherPrograms (vk::SourceCollections& programCollection, const GatherCaseBaseParams& baseParams, const vector<GatherArgs>& iterations)
1818 const int numIterations = (int)iterations.size();
1819 const string refZExpr = "v_normalizedCoord.x";
1820 const IVec2& offsetRange = baseParams.offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? getOffsetRange(baseParams.offsetSize) : IVec2(0);
1821 const bool usePixCoord = baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC;
1822 const bool useNormalizedCoord = usePixCoord || isDepthFormat(baseParams.textureFormat);
1823 const bool isDynamicOffset = baseParams.gatherType == GATHERTYPE_OFFSET_DYNAMIC;
1824 const bool isShadow = isDepthFormat(baseParams.textureFormat);
1825 const glu::DataType samplerType = getSamplerType(baseParams.textureType, baseParams.textureFormat);
1826 const int numDims = getNumTextureSamplingDimensions(baseParams.textureType);
1827 glu::VertexSource vert = genVertexShaderSource(requireGpuShader5(baseParams.gatherType, baseParams.offsetSize), numDims, isDynamicOffset || isShadow);
1829 // Check sampler type is valid.
1830 if (baseParams.levelMode != LevelMode::NORMAL)
1832 std::vector<glu::DataType> validSamplerTypes =
1834 glu::TYPE_SAMPLER_2D,
1835 glu::TYPE_SAMPLER_2D_ARRAY,
1836 glu::TYPE_INT_SAMPLER_2D,
1837 glu::TYPE_INT_SAMPLER_2D_ARRAY,
1838 glu::TYPE_UINT_SAMPLER_2D,
1839 glu::TYPE_UINT_SAMPLER_2D_ARRAY,
1842 if (baseParams.gatherType == GATHERTYPE_BASIC)
1844 static const std::vector<glu::DataType> kAdditionalTypes =
1846 glu::TYPE_SAMPLER_CUBE,
1847 glu::TYPE_SAMPLER_CUBE_ARRAY,
1848 glu::TYPE_INT_SAMPLER_CUBE,
1849 glu::TYPE_INT_SAMPLER_CUBE_ARRAY,
1850 glu::TYPE_UINT_SAMPLER_CUBE,
1851 glu::TYPE_UINT_SAMPLER_CUBE_ARRAY,
1854 std::copy(begin(kAdditionalTypes), end(kAdditionalTypes), std::back_inserter(validSamplerTypes));
1857 const auto itr = std::find(begin(validSamplerTypes), end(validSamplerTypes), samplerType);
1858 DE_ASSERT(itr != end(validSamplerTypes));
1859 DE_UNREF(itr); // For release builds.
1862 programCollection.glslSources.add("vert") << vert;
1864 for (int iterNdx = 0; iterNdx < numIterations; iterNdx++)
1866 const GatherArgs& gatherArgs = iterations[iterNdx];
1867 const string funcCall = genGatherFuncCall(baseParams.gatherType, baseParams.textureFormat, gatherArgs, baseParams.levelMode, baseParams.baseLevel, refZExpr, offsetRange, 1, baseParams.offsetSize, baseParams.sparseCase);
1868 glu::FragmentSource frag = genFragmentShaderSource(requireGpuShader5(baseParams.gatherType, baseParams.offsetSize), numDims, samplerType, funcCall, useNormalizedCoord, usePixCoord, baseParams.offsetSize, baseParams.sparseCase, baseParams.levelMode);
1870 programCollection.glslSources.add("frag_" + de::toString(iterNdx)) << frag;
1876 class TextureGather2DInstance : public TextureGatherInstance
1879 TextureGather2DInstance (Context& context,
1880 const GatherCaseBaseParams& baseParams,
1881 const IVec2& textureSize,
1882 const vector<GatherArgs>& iterations);
1883 virtual ~TextureGather2DInstance (void);
1886 virtual int getNumIterations (void) const { return (int)m_iterations.size(); }
1887 virtual GatherArgs getGatherArgs (int iterationNdx) const { return m_iterations[iterationNdx];}
1889 virtual TextureBindingSp createTexture (void);
1890 virtual vector<float> computeQuadTexCoord (int iterationNdx) const;
1891 virtual bool verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const;
1894 const IVec2 m_textureSize;
1895 const vector<GatherArgs> m_iterations;
1897 tcu::Texture2D m_swizzledTexture;
1900 TextureGather2DInstance::TextureGather2DInstance (Context& context,
1901 const GatherCaseBaseParams& baseParams,
1902 const IVec2& textureSize,
1903 const vector<GatherArgs>& iterations)
1904 : TextureGatherInstance (context, baseParams)
1905 , m_textureSize (textureSize)
1906 , m_iterations (iterations)
1907 , m_swizzledTexture (tcu::TextureFormat(), 1, 1)
1912 TextureGather2DInstance::~TextureGather2DInstance (void)
1916 vector<float> TextureGather2DInstance::computeQuadTexCoord (int /* iterationNdx */) const
1918 const bool biasMode = (m_baseParams.levelMode == LevelMode::AMD_BIAS);
1919 const auto bottomLeft = (biasMode ? Vec2(0.0f, 0.0f) : Vec2(-0.3f, -0.4f));
1920 const auto topRight = (biasMode ? Vec2(1.0f, 1.0f) : Vec2(1.5f, 1.6f));
1922 TextureTestUtil::computeQuadTexCoord2D(res, bottomLeft, topRight);
1926 TextureBindingSp TextureGather2DInstance::createTexture (void)
1928 TestLog& log = m_context.getTestContext().getLog();
1929 const tcu::TextureFormatInfo texFmtInfo = tcu::getTextureFormatInfo(m_baseParams.textureFormat);
1930 MovePtr<tcu::Texture2D> texture = MovePtr<tcu::Texture2D>(new tcu::Texture2D(m_baseParams.textureFormat, m_textureSize.x(), m_textureSize.y()));
1931 const tcu::Sampler sampler (m_baseParams.wrapS, m_baseParams.wrapT, tcu::Sampler::REPEAT_GL,
1932 m_baseParams.minFilter, m_baseParams.magFilter,
1933 0.0f /* LOD threshold */, true /* normalized coords */, m_baseParams.shadowCompareMode,
1934 0 /* compare channel */, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f) /* border color */, true /* seamless cube*/);
1937 const int levelBegin = ((m_baseParams.levelMode == LevelMode::NORMAL) ? m_baseParams.baseLevel : 0);
1938 const int levelEnd = texture->getNumLevels();
1939 DE_ASSERT(m_baseParams.baseLevel < texture->getNumLevels());
1941 for (int levelNdx = levelBegin; levelNdx < levelEnd; levelNdx++)
1943 texture->allocLevel(levelNdx);
1944 const PixelBufferAccess& level = texture->getLevel(levelNdx);
1945 fillWithRandomColorTiles(level, texFmtInfo.valueMin, texFmtInfo.valueMax, (deUint32)m_context.getTestContext().getCommandLine().getBaseSeed());
1946 log << TestLog::Image("InputTextureLevel" + de::toString(levelNdx), "Input texture, level " + de::toString(levelNdx), level)
1947 << TestLog::Message << "Note: texture level's size is " << IVec2(level.getWidth(), level.getHeight()) << TestLog::EndMessage;
1950 swizzleTexture(m_swizzledTexture, *texture, m_baseParams.textureSwizzle);
1953 return TextureBindingSp(new TextureBinding(texture.release(), sampler));
1956 bool TextureGather2DInstance::verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const
1959 computeTexCoordVecs(computeQuadTexCoord(iterationNdx), texCoords);
1960 return TextureGatherInstance::verify(rendered, getOneLevelSubView(tcu::Texture2DView(m_swizzledTexture), m_baseParams.baseLevel), texCoords, m_iterations[iterationNdx]);
1963 class TextureGather2DCase : public TestCase
1966 TextureGather2DCase (tcu::TestContext& testCtx,
1968 const string& description,
1969 const GatherType gatherType,
1970 const OffsetSize offsetSize,
1971 const tcu::TextureFormat textureFormat,
1972 const tcu::Sampler::CompareMode shadowCompareMode,
1973 const tcu::Sampler::WrapMode wrapS,
1974 const tcu::Sampler::WrapMode wrapT,
1975 const MaybeTextureSwizzle& textureSwizzle,
1976 const tcu::Sampler::FilterMode minFilter,
1977 const tcu::Sampler::FilterMode magFilter,
1978 const LevelMode levelMode,
1979 const int baseLevel,
1980 const deUint32 flags,
1981 const IVec2& textureSize,
1982 const ImageBackingMode sparseCase);
1983 virtual ~TextureGather2DCase (void);
1985 virtual void initPrograms (vk::SourceCollections& dst) const;
1986 virtual TestInstance* createInstance (Context& context) const;
1987 virtual void checkSupport (Context& context) const;
1990 const GatherCaseBaseParams m_baseParams;
1991 const IVec2 m_textureSize;
1994 TextureGather2DCase::TextureGather2DCase (tcu::TestContext& testCtx,
1996 const string& description,
1997 const GatherType gatherType,
1998 const OffsetSize offsetSize,
1999 const tcu::TextureFormat textureFormat,
2000 const tcu::Sampler::CompareMode shadowCompareMode,
2001 const tcu::Sampler::WrapMode wrapS,
2002 const tcu::Sampler::WrapMode wrapT,
2003 const MaybeTextureSwizzle& textureSwizzle,
2004 const tcu::Sampler::FilterMode minFilter,
2005 const tcu::Sampler::FilterMode magFilter,
2006 const LevelMode levelMode,
2007 const int baseLevel,
2008 const deUint32 flags,
2009 const IVec2& textureSize,
2010 const ImageBackingMode sparseCase)
2011 : TestCase (testCtx, name, description)
2012 , m_baseParams (TEXTURETYPE_2D, gatherType, offsetSize, textureFormat, shadowCompareMode, wrapS, wrapT, textureSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, sparseCase)
2013 , m_textureSize (textureSize)
2017 TextureGather2DCase::~TextureGather2DCase (void)
2021 void TextureGather2DCase::initPrograms (vk::SourceCollections& dst) const
2023 const vector<GatherArgs> iterations = generateBasic2DCaseIterations(m_baseParams.gatherType,
2024 m_baseParams.levelMode,
2025 m_baseParams.textureFormat,
2026 m_baseParams.offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? getOffsetRange(m_baseParams.offsetSize) : IVec2(0));
2028 genGatherPrograms(dst, m_baseParams, iterations);
2031 TestInstance* TextureGather2DCase::createInstance (Context& context) const
2033 const vector<GatherArgs> iterations = generateBasic2DCaseIterations(m_baseParams.gatherType,
2034 m_baseParams.levelMode,
2035 m_baseParams.textureFormat,
2036 getOffsetRange(m_baseParams.offsetSize, context.getDeviceProperties().limits));
2038 return new TextureGather2DInstance(context, m_baseParams, m_textureSize, iterations);
2041 void TextureGather2DCase::checkSupport(Context& context) const
2043 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_IMAGE_GATHER_EXTENDED);
2044 checkMutableComparisonSamplersSupport(context, m_baseParams);
2049 struct Gather2DArrayArgs
2051 GatherArgs gatherArgs;
2054 operator GatherArgs() const { return gatherArgs; }
2057 vector<Gather2DArrayArgs> generate2DArrayCaseIterations (GatherType gatherType,
2058 LevelMode levelMode,
2059 const tcu::TextureFormat& textureFormat,
2060 const IVec2& offsetRange,
2061 const IVec3& textureSize)
2063 const vector<GatherArgs> basicIterations = generateBasic2DCaseIterations(gatherType, levelMode, textureFormat, offsetRange);
2064 vector<Gather2DArrayArgs> iterations;
2066 // \note Out-of-bounds layer indices are tested too.
2067 for (int layerNdx = -1; layerNdx < textureSize.z()+1; layerNdx++)
2069 // Don't duplicate all cases for all layers.
2072 for (int basicNdx = 0; basicNdx < (int)basicIterations.size(); basicNdx++)
2074 iterations.push_back(Gather2DArrayArgs());
2075 iterations.back().gatherArgs = basicIterations[basicNdx];
2076 iterations.back().layerNdx = layerNdx;
2081 // For other layers than 0, only test one component and one set of offsets per layer.
2082 for (int basicNdx = 0; basicNdx < (int)basicIterations.size(); basicNdx++)
2084 if (isDepthFormat(textureFormat) || basicIterations[basicNdx].componentNdx == (layerNdx + 2) % 4)
2086 iterations.push_back(Gather2DArrayArgs());
2087 iterations.back().gatherArgs = basicIterations[basicNdx];
2088 iterations.back().layerNdx = layerNdx;
2098 class TextureGather2DArrayInstance : public TextureGatherInstance
2101 TextureGather2DArrayInstance (Context& context,
2102 const GatherCaseBaseParams& baseParams,
2103 const IVec3& textureSize,
2104 const vector<Gather2DArrayArgs>& iterations);
2105 virtual ~TextureGather2DArrayInstance (void);
2108 virtual int getNumIterations (void) const { return (int)m_iterations.size(); }
2109 virtual GatherArgs getGatherArgs (int iterationNdx) const { return m_iterations[iterationNdx].gatherArgs; }
2111 virtual TextureBindingSp createTexture (void);
2112 virtual vector<float> computeQuadTexCoord (int iterationNdx) const;
2113 virtual bool verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const;
2116 const IVec3 m_textureSize;
2117 const vector<Gather2DArrayArgs> m_iterations;
2119 tcu::Texture2DArray m_swizzledTexture;
2122 TextureGather2DArrayInstance::TextureGather2DArrayInstance (Context& context,
2123 const GatherCaseBaseParams& baseParams,
2124 const IVec3& textureSize,
2125 const vector<Gather2DArrayArgs>& iterations)
2126 : TextureGatherInstance (context, baseParams)
2127 , m_textureSize (textureSize)
2128 , m_iterations (iterations)
2129 , m_swizzledTexture (tcu::TextureFormat(), 1, 1, 1)
2134 TextureGather2DArrayInstance::~TextureGather2DArrayInstance (void)
2138 vector<float> TextureGather2DArrayInstance::computeQuadTexCoord (int iterationNdx) const
2140 const bool biasMode = (m_baseParams.levelMode == LevelMode::AMD_BIAS);
2141 const auto bottomLeft = (biasMode ? Vec2(0.0f, 0.0f) : Vec2(-0.3f, -0.4f));
2142 const auto topRight = (biasMode ? Vec2(1.0f, 1.0f) : Vec2(1.5f, 1.6f));
2144 TextureTestUtil::computeQuadTexCoord2DArray(res, m_iterations[iterationNdx].layerNdx, bottomLeft, topRight);
2148 TextureBindingSp TextureGather2DArrayInstance::createTexture (void)
2150 TestLog& log = m_context.getTestContext().getLog();
2151 const tcu::TextureFormatInfo texFmtInfo = tcu::getTextureFormatInfo(m_baseParams.textureFormat);
2152 MovePtr<tcu::Texture2DArray> texture = MovePtr<tcu::Texture2DArray>(new tcu::Texture2DArray(m_baseParams.textureFormat, m_textureSize.x(), m_textureSize.y(), m_textureSize.z()));
2153 const tcu::Sampler sampler (m_baseParams.wrapS, m_baseParams.wrapT, tcu::Sampler::REPEAT_GL,
2154 m_baseParams.minFilter, m_baseParams.magFilter,
2155 0.0f /* LOD threshold */, true /* normalized coords */, m_baseParams.shadowCompareMode,
2156 0 /* compare channel */, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f) /* border color */, true /* seamless cube*/);
2159 const int levelBegin = ((m_baseParams.levelMode == LevelMode::NORMAL) ? m_baseParams.baseLevel : 0);
2160 const int levelEnd = texture->getNumLevels();
2161 DE_ASSERT(m_baseParams.baseLevel < texture->getNumLevels());
2163 for (int levelNdx = levelBegin; levelNdx < levelEnd; levelNdx++)
2165 texture->allocLevel(levelNdx);
2166 const PixelBufferAccess& level = texture->getLevel(levelNdx);
2167 fillWithRandomColorTiles(level, texFmtInfo.valueMin, texFmtInfo.valueMax, (deUint32)m_context.getTestContext().getCommandLine().getBaseSeed());
2169 log << TestLog::ImageSet("InputTextureLevel", "Input texture, level " + de::toString(levelNdx));
2170 for (int layerNdx = 0; layerNdx < m_textureSize.z(); layerNdx++)
2171 log << TestLog::Image("InputTextureLevel" + de::toString(layerNdx) + "Layer" + de::toString(layerNdx),
2172 "Layer " + de::toString(layerNdx),
2173 tcu::getSubregion(level, 0, 0, layerNdx, level.getWidth(), level.getHeight(), 1));
2174 log << TestLog::EndImageSet
2175 << TestLog::Message << "Note: texture level's size is " << IVec3(level.getWidth(), level.getHeight(), level.getDepth()) << TestLog::EndMessage;
2178 swizzleTexture(m_swizzledTexture, *texture, m_baseParams.textureSwizzle);
2181 return TextureBindingSp(new TextureBinding(texture.release(), sampler));
2184 bool TextureGather2DArrayInstance::verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const
2187 computeTexCoordVecs(computeQuadTexCoord(iterationNdx), texCoords);
2188 return TextureGatherInstance::verify(rendered, getOneLevelSubView(tcu::Texture2DArrayView(m_swizzledTexture), m_baseParams.baseLevel), texCoords, m_iterations[iterationNdx].gatherArgs);
2191 class TextureGather2DArrayCase : public TestCase
2194 TextureGather2DArrayCase (tcu::TestContext& testCtx,
2196 const string& description,
2197 const GatherType gatherType,
2198 const OffsetSize offsetSize,
2199 const tcu::TextureFormat textureFormat,
2200 const tcu::Sampler::CompareMode shadowCompareMode,
2201 const tcu::Sampler::WrapMode wrapS,
2202 const tcu::Sampler::WrapMode wrapT,
2203 const MaybeTextureSwizzle& textureSwizzle,
2204 const tcu::Sampler::FilterMode minFilter,
2205 const tcu::Sampler::FilterMode magFilter,
2206 const LevelMode levelMode,
2207 const int baseLevel,
2208 const deUint32 flags,
2209 const IVec3& textureSize,
2210 const ImageBackingMode sparseCase);
2211 virtual ~TextureGather2DArrayCase (void);
2213 virtual void initPrograms (vk::SourceCollections& dst) const;
2214 virtual TestInstance* createInstance (Context& context) const;
2215 virtual void checkSupport (Context& context) const;
2218 const GatherCaseBaseParams m_baseParams;
2219 const IVec3 m_textureSize;
2222 TextureGather2DArrayCase::TextureGather2DArrayCase (tcu::TestContext& testCtx,
2224 const string& description,
2225 const GatherType gatherType,
2226 const OffsetSize offsetSize,
2227 const tcu::TextureFormat textureFormat,
2228 const tcu::Sampler::CompareMode shadowCompareMode,
2229 const tcu::Sampler::WrapMode wrapS,
2230 const tcu::Sampler::WrapMode wrapT,
2231 const MaybeTextureSwizzle& textureSwizzle,
2232 const tcu::Sampler::FilterMode minFilter,
2233 const tcu::Sampler::FilterMode magFilter,
2234 const LevelMode levelMode,
2235 const int baseLevel,
2236 const deUint32 flags,
2237 const IVec3& textureSize,
2238 const ImageBackingMode sparseCase)
2239 : TestCase (testCtx, name, description)
2240 , m_baseParams (TEXTURETYPE_2D_ARRAY, gatherType, offsetSize, textureFormat, shadowCompareMode, wrapS, wrapT, textureSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, sparseCase)
2241 , m_textureSize (textureSize)
2245 TextureGather2DArrayCase::~TextureGather2DArrayCase (void)
2249 void TextureGather2DArrayCase::initPrograms (vk::SourceCollections& dst) const
2251 const vector<Gather2DArrayArgs> iterations = generate2DArrayCaseIterations(m_baseParams.gatherType,
2252 m_baseParams.levelMode,
2253 m_baseParams.textureFormat,
2254 m_baseParams.offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? getOffsetRange(m_baseParams.offsetSize) : IVec2(0),
2257 genGatherPrograms(dst, m_baseParams, vector<GatherArgs>(iterations.begin(), iterations.end()));
2260 TestInstance* TextureGather2DArrayCase::createInstance (Context& context) const
2262 const vector<Gather2DArrayArgs> iterations = generate2DArrayCaseIterations(m_baseParams.gatherType,
2263 m_baseParams.levelMode,
2264 m_baseParams.textureFormat,
2265 getOffsetRange(m_baseParams.offsetSize, context.getDeviceProperties().limits),
2268 return new TextureGather2DArrayInstance(context, m_baseParams, m_textureSize, iterations);
2271 void TextureGather2DArrayCase::checkSupport(Context& context) const
2273 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_IMAGE_GATHER_EXTENDED);
2274 checkMutableComparisonSamplersSupport(context, m_baseParams);
2279 struct GatherCubeArgs
2281 GatherArgs gatherArgs;
2284 operator GatherArgs() const { return gatherArgs; }
2287 vector<GatherCubeArgs> generateCubeCaseIterations (GatherType gatherType, LevelMode levelMode, const tcu::TextureFormat& textureFormat, const IVec2& offsetRange)
2289 const vector<GatherArgs> basicIterations = generateBasic2DCaseIterations(gatherType, levelMode, textureFormat, offsetRange);
2290 vector<GatherCubeArgs> iterations;
2292 for (int cubeFaceI = 0; cubeFaceI < tcu::CUBEFACE_LAST; cubeFaceI++)
2294 const tcu::CubeFace cubeFace = (tcu::CubeFace)cubeFaceI;
2296 // Don't duplicate all cases for all faces.
2299 for (int basicNdx = 0; basicNdx < (int)basicIterations.size(); basicNdx++)
2301 iterations.push_back(GatherCubeArgs());
2302 iterations.back().gatherArgs = basicIterations[basicNdx];
2303 iterations.back().face = cubeFace;
2308 // For other faces than first, only test one component per face.
2309 for (int basicNdx = 0; basicNdx < (int)basicIterations.size(); basicNdx++)
2311 if (isDepthFormat(textureFormat) || basicIterations[basicNdx].componentNdx == cubeFaceI % 4)
2313 iterations.push_back(GatherCubeArgs());
2314 iterations.back().gatherArgs = basicIterations[basicNdx];
2315 iterations.back().face = cubeFace;
2325 class TextureGatherCubeInstance : public TextureGatherInstance
2328 TextureGatherCubeInstance (Context& context,
2329 const GatherCaseBaseParams& baseParams,
2330 const int textureSize,
2331 const vector<GatherCubeArgs>& iterations);
2332 virtual ~TextureGatherCubeInstance (void);
2335 virtual int getNumIterations (void) const { return (int)m_iterations.size(); }
2336 virtual GatherArgs getGatherArgs (int iterationNdx) const { return m_iterations[iterationNdx].gatherArgs; }
2338 virtual TextureBindingSp createTexture (void);
2339 virtual vector<float> computeQuadTexCoord (int iterationNdx) const;
2340 virtual bool verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const;
2343 const int m_textureSize;
2344 const vector<GatherCubeArgs> m_iterations;
2346 tcu::TextureCube m_swizzledTexture;
2349 TextureGatherCubeInstance::TextureGatherCubeInstance (Context& context,
2350 const GatherCaseBaseParams& baseParams,
2351 const int textureSize,
2352 const vector<GatherCubeArgs>& iterations)
2353 : TextureGatherInstance (context, baseParams)
2354 , m_textureSize (textureSize)
2355 , m_iterations (iterations)
2356 , m_swizzledTexture (tcu::TextureFormat(), 1)
2361 TextureGatherCubeInstance::~TextureGatherCubeInstance (void)
2365 vector<float> TextureGatherCubeInstance::computeQuadTexCoord (int iterationNdx) const
2367 const bool biasMode = (m_baseParams.levelMode == LevelMode::AMD_BIAS);
2368 const bool corners = (m_baseParams.flags & GATHERCASE_DONT_SAMPLE_CUBE_CORNERS) == 0;
2369 const Vec2 minC = (biasMode ? Vec2(-1.0f) : (corners ? Vec2(-1.2f) : Vec2(-0.6f, -1.2f)));
2370 const Vec2 maxC = (biasMode ? Vec2( 1.0f) : (corners ? Vec2( 1.2f) : Vec2( 0.6f, 1.2f)));
2372 TextureTestUtil::computeQuadTexCoordCube(res, m_iterations[iterationNdx].face, minC, maxC);
2376 TextureBindingSp TextureGatherCubeInstance::createTexture (void)
2378 TestLog& log = m_context.getTestContext().getLog();
2379 const tcu::TextureFormatInfo texFmtInfo = tcu::getTextureFormatInfo(m_baseParams.textureFormat);
2380 MovePtr<tcu::TextureCube> texture = MovePtr<tcu::TextureCube>(new tcu::TextureCube(m_baseParams.textureFormat, m_textureSize));
2381 const tcu::Sampler sampler (m_baseParams.wrapS, m_baseParams.wrapT, tcu::Sampler::REPEAT_GL,
2382 m_baseParams.minFilter, m_baseParams.magFilter,
2383 0.0f /* LOD threshold */, true /* normalized coords */, m_baseParams.shadowCompareMode,
2384 0 /* cmp channel */, tcu::Vec4(0.0f) /* border color */, true /* seamless cube map */);
2387 const int levelBegin = ((m_baseParams.levelMode == LevelMode::NORMAL) ? m_baseParams.baseLevel : 0);
2388 const int levelEnd = texture->getNumLevels();
2389 DE_ASSERT(m_baseParams.baseLevel < texture->getNumLevels());
2391 for (int levelNdx = levelBegin; levelNdx < levelEnd; levelNdx++)
2393 log << TestLog::ImageSet("InputTextureLevel" + de::toString(levelNdx), "Input texture, level " + de::toString(levelNdx));
2395 for (int cubeFaceI = 0; cubeFaceI < tcu::CUBEFACE_LAST; cubeFaceI++)
2397 const tcu::CubeFace cubeFace = (tcu::CubeFace)cubeFaceI;
2398 texture->allocLevel(cubeFace, levelNdx);
2399 const PixelBufferAccess& levelFace = texture->getLevelFace(levelNdx, cubeFace);
2400 fillWithRandomColorTiles(levelFace, texFmtInfo.valueMin, texFmtInfo.valueMax, (deUint32)m_context.getTestContext().getCommandLine().getBaseSeed() ^ (deUint32)cubeFaceI);
2402 log << TestLog::Image("InputTextureLevel" + de::toString(levelNdx) + "Face" + de::toString((int)cubeFace), de::toString(cubeFace), levelFace);
2405 log << TestLog::EndImageSet
2406 << TestLog::Message << "Note: texture level's size is " << texture->getLevelFace(levelNdx, tcu::CUBEFACE_NEGATIVE_X).getWidth() << TestLog::EndMessage;
2409 swizzleTexture(m_swizzledTexture, *texture, m_baseParams.textureSwizzle);
2412 return TextureBindingSp(new TextureBinding(texture.release(), sampler));
2415 bool TextureGatherCubeInstance::verify (int iterationNdx, const ConstPixelBufferAccess& rendered) const
2418 computeTexCoordVecs(computeQuadTexCoord(iterationNdx), texCoords);
2419 return TextureGatherInstance::verify(rendered, getOneLevelSubView(tcu::TextureCubeView(m_swizzledTexture), m_baseParams.baseLevel), texCoords, m_iterations[iterationNdx].gatherArgs);
2422 // \note Cube case always uses just basic textureGather(); offset versions are not defined for cube maps.
2423 class TextureGatherCubeCase : public TestCase
2426 TextureGatherCubeCase (tcu::TestContext& testCtx,
2428 const string& description,
2429 const tcu::TextureFormat textureFormat,
2430 const tcu::Sampler::CompareMode shadowCompareMode,
2431 const tcu::Sampler::WrapMode wrapS,
2432 const tcu::Sampler::WrapMode wrapT,
2433 const MaybeTextureSwizzle& textureSwizzle,
2434 const tcu::Sampler::FilterMode minFilter,
2435 const tcu::Sampler::FilterMode magFilter,
2436 const LevelMode levelMode,
2437 const int baseLevel,
2438 const deUint32 flags,
2439 const int textureSize,
2440 const ImageBackingMode sparseCase);
2441 virtual ~TextureGatherCubeCase (void);
2443 virtual void initPrograms (vk::SourceCollections& dst) const;
2444 virtual TestInstance* createInstance (Context& context) const;
2445 virtual void checkSupport (Context& context) const;
2448 const GatherCaseBaseParams m_baseParams;
2449 const int m_textureSize;
2452 TextureGatherCubeCase::TextureGatherCubeCase (tcu::TestContext& testCtx,
2454 const string& description,
2455 const tcu::TextureFormat textureFormat,
2456 const tcu::Sampler::CompareMode shadowCompareMode,
2457 const tcu::Sampler::WrapMode wrapS,
2458 const tcu::Sampler::WrapMode wrapT,
2459 const MaybeTextureSwizzle& textureSwizzle,
2460 const tcu::Sampler::FilterMode minFilter,
2461 const tcu::Sampler::FilterMode magFilter,
2462 const LevelMode levelMode,
2463 const int baseLevel,
2464 const deUint32 flags,
2465 const int textureSize,
2466 const ImageBackingMode sparseCase)
2467 : TestCase (testCtx, name, description)
2468 , m_baseParams (TEXTURETYPE_CUBE, GATHERTYPE_BASIC, OFFSETSIZE_NONE, textureFormat, shadowCompareMode, wrapS, wrapT, textureSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, sparseCase)
2469 , m_textureSize (textureSize)
2473 TextureGatherCubeCase::~TextureGatherCubeCase (void)
2477 void TextureGatherCubeCase::initPrograms (vk::SourceCollections& dst) const
2479 const vector<GatherCubeArgs> iterations = generateCubeCaseIterations(m_baseParams.gatherType,
2480 m_baseParams.levelMode,
2481 m_baseParams.textureFormat,
2482 m_baseParams.offsetSize != OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? getOffsetRange(m_baseParams.offsetSize) : IVec2(0));
2484 genGatherPrograms(dst, m_baseParams, vector<GatherArgs>(iterations.begin(), iterations.end()));
2487 TestInstance* TextureGatherCubeCase::createInstance (Context& context) const
2489 const vector<GatherCubeArgs> iterations = generateCubeCaseIterations(m_baseParams.gatherType,
2490 m_baseParams.levelMode,
2491 m_baseParams.textureFormat,
2492 getOffsetRange(m_baseParams.offsetSize, context.getDeviceProperties().limits));
2494 return new TextureGatherCubeInstance(context, m_baseParams, m_textureSize, iterations);
2497 void TextureGatherCubeCase::checkSupport(Context& context) const
2499 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_IMAGE_GATHER_EXTENDED);
2500 checkMutableComparisonSamplersSupport(context, m_baseParams);
2503 class TextureGatherTests : public tcu::TestCaseGroup
2506 TextureGatherTests (tcu::TestContext& context);
2507 virtual ~TextureGatherTests (void);
2508 virtual void init (void);
2511 TextureGatherTests (const TextureGatherTests&); // not allowed!
2512 TextureGatherTests& operator= (const TextureGatherTests&); // not allowed!
2515 TextureGatherTests::TextureGatherTests (tcu::TestContext& context)
2516 : TestCaseGroup(context, "texture_gather", "textureGather* tests")
2520 TextureGatherTests::~TextureGatherTests (void)
2524 static inline TestCase* makeTextureGatherCase (TextureType textureType,
2525 tcu::TestContext& testCtx,
2527 const string& description,
2528 GatherType gatherType,
2529 OffsetSize offsetSize,
2530 tcu::TextureFormat textureFormat,
2531 tcu::Sampler::CompareMode shadowCompareMode,
2532 tcu::Sampler::WrapMode wrapS,
2533 tcu::Sampler::WrapMode wrapT,
2534 const MaybeTextureSwizzle& texSwizzle,
2535 tcu::Sampler::FilterMode minFilter,
2536 tcu::Sampler::FilterMode magFilter,
2537 LevelMode levelMode,
2539 const IVec3& textureSize,
2541 const ImageBackingMode sparseCase = ShaderRenderCaseInstance::IMAGE_BACKING_MODE_REGULAR)
2543 switch (textureType)
2545 case TEXTURETYPE_2D:
2546 return new TextureGather2DCase(testCtx, name, description, gatherType, offsetSize, textureFormat, shadowCompareMode,
2547 wrapS, wrapT, texSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, textureSize.swizzle(0, 1), sparseCase);
2549 case TEXTURETYPE_2D_ARRAY:
2550 return new TextureGather2DArrayCase(testCtx, name, description, gatherType, offsetSize, textureFormat, shadowCompareMode,
2551 wrapS, wrapT, texSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, textureSize, sparseCase);
2553 case TEXTURETYPE_CUBE:
2554 DE_ASSERT(gatherType == GATHERTYPE_BASIC);
2555 DE_ASSERT(offsetSize == OFFSETSIZE_NONE);
2556 return new TextureGatherCubeCase(testCtx, name, description, textureFormat, shadowCompareMode,
2557 wrapS, wrapT, texSwizzle, minFilter, magFilter, levelMode, baseLevel, flags, textureSize.x(), sparseCase);
2565 static inline const char* compareModeName (tcu::Sampler::CompareMode mode)
2569 case tcu::Sampler::COMPAREMODE_LESS: return "less";
2570 case tcu::Sampler::COMPAREMODE_LESS_OR_EQUAL: return "less_or_equal";
2571 case tcu::Sampler::COMPAREMODE_GREATER: return "greater";
2572 case tcu::Sampler::COMPAREMODE_GREATER_OR_EQUAL: return "greater_or_equal";
2573 case tcu::Sampler::COMPAREMODE_EQUAL: return "equal";
2574 case tcu::Sampler::COMPAREMODE_NOT_EQUAL: return "not_equal";
2575 case tcu::Sampler::COMPAREMODE_ALWAYS: return "always";
2576 case tcu::Sampler::COMPAREMODE_NEVER: return "never";
2577 default: DE_ASSERT(false); return DE_NULL;
2581 void TextureGatherTests::init (void)
2589 { "2d", TEXTURETYPE_2D },
2590 { "2d_array", TEXTURETYPE_2D_ARRAY },
2591 { "cube", TEXTURETYPE_CUBE }
2597 tcu::TextureFormat format;
2600 { "rgba8", tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8) },
2601 { "rgba8ui", tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT8) },
2602 { "rgba8i", tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT8) },
2603 { "depth32f", tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT) }
2612 { "size_pot", IVec3(64, 64, 3) },
2613 { "size_npot", IVec3(17, 23, 3) }
2619 tcu::Sampler::WrapMode mode;
2622 { "clamp_to_edge", tcu::Sampler::CLAMP_TO_EDGE },
2623 { "repeat", tcu::Sampler::REPEAT_GL },
2624 { "mirrored_repeat", tcu::Sampler::MIRRORED_REPEAT_GL }
2627 for (int gatherTypeI = 0; gatherTypeI < GATHERTYPE_LAST; gatherTypeI++)
2629 const GatherType gatherType = (GatherType)gatherTypeI;
2630 TestCaseGroup* const gatherTypeGroup = new TestCaseGroup(m_testCtx, gatherTypeName(gatherType), gatherTypeDescription(gatherType));
2631 addChild(gatherTypeGroup);
2633 for (int offsetSizeI = 0; offsetSizeI < OFFSETSIZE_LAST; offsetSizeI++)
2635 const OffsetSize offsetSize = (OffsetSize)offsetSizeI;
2636 if ((gatherType == GATHERTYPE_BASIC) != (offsetSize == OFFSETSIZE_NONE))
2639 if (gatherType == GATHERTYPE_OFFSETS && offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM) // \note offsets argument must be compile-time constant
2642 TestCaseGroup* const offsetSizeGroup = offsetSize == OFFSETSIZE_NONE ?
2644 new TestCaseGroup(m_testCtx,
2645 offsetSize == OFFSETSIZE_MINIMUM_REQUIRED ? "min_required_offset"
2646 : offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? "implementation_offset"
2648 offsetSize == OFFSETSIZE_MINIMUM_REQUIRED ? "Use offsets within Vulkan minimum required range"
2649 : offsetSize == OFFSETSIZE_IMPLEMENTATION_MAXIMUM ? "Use offsets within the implementation range"
2652 if (offsetSizeGroup != gatherTypeGroup)
2653 gatherTypeGroup->addChild(offsetSizeGroup);
2655 for (int textureTypeNdx = 0; textureTypeNdx < DE_LENGTH_OF_ARRAY(textureTypes); textureTypeNdx++)
2657 const TextureType textureType = textureTypes[textureTypeNdx].type;
2659 if (textureType == TEXTURETYPE_CUBE && gatherType != GATHERTYPE_BASIC)
2662 TestCaseGroup* const textureTypeGroup = new TestCaseGroup(m_testCtx, textureTypes[textureTypeNdx].name, "");
2663 offsetSizeGroup->addChild(textureTypeGroup);
2665 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
2667 const tcu::TextureFormat& format = formats[formatNdx].format;
2668 TestCaseGroup* const formatGroup = new TestCaseGroup(m_testCtx, formats[formatNdx].name, "");
2669 textureTypeGroup->addChild(formatGroup);
2671 for (int noCornersI = 0; noCornersI <= ((textureType == TEXTURETYPE_CUBE)?1:0); noCornersI++)
2673 const bool noCorners = noCornersI!= 0;
2674 TestCaseGroup* const cornersGroup = noCorners
2675 ? new TestCaseGroup(m_testCtx, "no_corners", "Test case variants that don't sample around cube map corners")
2678 if (formatGroup != cornersGroup)
2679 formatGroup->addChild(cornersGroup);
2681 for (int textureSizeNdx = 0; textureSizeNdx < DE_LENGTH_OF_ARRAY(textureSizes); textureSizeNdx++)
2683 const IVec3& textureSize = textureSizes[textureSizeNdx].size;
2684 TestCaseGroup* const textureSizeGroup = new TestCaseGroup(m_testCtx, textureSizes[textureSizeNdx].name, "");
2685 cornersGroup->addChild(textureSizeGroup);
2687 for (int compareModeI = 0; compareModeI < tcu::Sampler::COMPAREMODE_LAST; compareModeI++)
2689 const tcu::Sampler::CompareMode compareMode = (tcu::Sampler::CompareMode)compareModeI;
2691 if ((compareMode != tcu::Sampler::COMPAREMODE_NONE) != isDepthFormat(format))
2694 if (compareMode != tcu::Sampler::COMPAREMODE_NONE &&
2695 compareMode != tcu::Sampler::COMPAREMODE_LESS &&
2696 compareMode != tcu::Sampler::COMPAREMODE_GREATER)
2699 TestCaseGroup* const compareModeGroup = compareMode == tcu::Sampler::COMPAREMODE_NONE ?
2701 new TestCaseGroup(m_testCtx,
2702 (string() + "compare_" + compareModeName(compareMode)).c_str(),
2704 if (compareModeGroup != textureSizeGroup)
2705 textureSizeGroup->addChild(compareModeGroup);
2707 for (int wrapCaseNdx = 0; wrapCaseNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapCaseNdx++)
2709 const int wrapSNdx = wrapCaseNdx;
2710 const int wrapTNdx = (wrapCaseNdx + 1) % DE_LENGTH_OF_ARRAY(wrapModes);
2711 const tcu::Sampler::WrapMode wrapS = wrapModes[wrapSNdx].mode;
2712 const tcu::Sampler::WrapMode wrapT = wrapModes[wrapTNdx].mode;
2714 const string caseName = string() + wrapModes[wrapSNdx].name + "_" + wrapModes[wrapTNdx].name;
2716 compareModeGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, caseName.c_str(), "", gatherType, offsetSize, format, compareMode, wrapS, wrapT,
2717 MaybeTextureSwizzle::createNoneTextureSwizzle(), tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, LevelMode::NORMAL, 0, textureSize,
2718 noCorners ? GATHERCASE_DONT_SAMPLE_CUBE_CORNERS : 0));
2719 #ifndef CTS_USES_VULKANSC
2720 compareModeGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, "sparse_" + caseName, "", gatherType, offsetSize, format, compareMode, wrapS, wrapT,
2721 MaybeTextureSwizzle::createNoneTextureSwizzle(), tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, LevelMode::NORMAL, 0, textureSize,
2722 noCorners ? GATHERCASE_DONT_SAMPLE_CUBE_CORNERS : 0, ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE));
2723 #endif // CTS_USES_VULKANSC
2729 if (offsetSize != OFFSETSIZE_MINIMUM_REQUIRED || gatherType == GATHERTYPE_OFFSETS) // Don't test all features for both offset size types, as they should be rather orthogonal.
2731 if (!isDepthFormat(format))
2733 TestCaseGroup* const swizzleGroup = new TestCaseGroup(m_testCtx, "texture_swizzle", "");
2734 formatGroup->addChild(swizzleGroup);
2736 DE_STATIC_ASSERT(TEXTURESWIZZLECOMPONENT_R == 0);
2737 for (int swizzleCaseNdx = 0; swizzleCaseNdx < TEXTURESWIZZLECOMPONENT_LAST; swizzleCaseNdx++)
2739 MaybeTextureSwizzle swizzle = MaybeTextureSwizzle::createSomeTextureSwizzle();
2742 for (int i = 0; i < 4; i++)
2744 swizzle.getSwizzle()[i] = (TextureSwizzleComponent)((swizzleCaseNdx + i) % (int)TEXTURESWIZZLECOMPONENT_LAST);
2745 caseName += (i > 0 ? "_" : "") + de::toLower(de::toString(swizzle.getSwizzle()[i]));
2748 swizzleGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, caseName.c_str(), "", gatherType, offsetSize, format,
2749 tcu::Sampler::COMPAREMODE_NONE, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2750 swizzle, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, LevelMode::NORMAL, 0, IVec3(64, 64, 3)));
2751 #ifndef CTS_USES_VULKANSC
2752 swizzleGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, "sparse_" + caseName, "", gatherType, offsetSize, format,
2753 tcu::Sampler::COMPAREMODE_NONE, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2754 swizzle, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, LevelMode::NORMAL, 0, IVec3(64, 64, 3), 0, ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE));
2755 #endif // CTS_USES_VULKANSC
2760 TestCaseGroup* const filterModeGroup = new TestCaseGroup(m_testCtx, "filter_mode", "Test that filter modes have no effect");
2761 formatGroup->addChild(filterModeGroup);
2766 tcu::Sampler::FilterMode filter;
2769 { "linear", tcu::Sampler::LINEAR },
2770 { "nearest", tcu::Sampler::NEAREST }
2776 tcu::Sampler::FilterMode filter;
2779 // \note Don't test NEAREST here, as it's covered by other cases.
2780 { "linear", tcu::Sampler::LINEAR },
2781 { "nearest_mipmap_nearest", tcu::Sampler::NEAREST_MIPMAP_NEAREST },
2782 { "nearest_mipmap_linear", tcu::Sampler::NEAREST_MIPMAP_LINEAR },
2783 { "linear_mipmap_nearest", tcu::Sampler::LINEAR_MIPMAP_NEAREST },
2784 { "linear_mipmap_linear", tcu::Sampler::LINEAR_MIPMAP_LINEAR },
2787 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilters); minFilterNdx++)
2788 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilters); magFilterNdx++)
2790 const tcu::Sampler::FilterMode minFilter = minFilters[minFilterNdx].filter;
2791 const tcu::Sampler::FilterMode magFilter = magFilters[magFilterNdx].filter;
2792 const tcu::Sampler::CompareMode compareMode = isDepthFormat(format) ? tcu::Sampler::COMPAREMODE_LESS : tcu::Sampler::COMPAREMODE_NONE;
2794 if ((isUnormFormatType(format.type) || isDepthFormat(format)) && magFilter == tcu::Sampler::NEAREST)
2795 continue; // Covered by other cases.
2796 if ((isUIntFormatType(format.type) || isSIntFormatType(format.type)) &&
2797 (magFilter != tcu::Sampler::NEAREST || minFilter != tcu::Sampler::NEAREST_MIPMAP_NEAREST))
2800 const string caseName = string() + "min_" + minFilters[minFilterNdx].name + "_mag_" + magFilters[magFilterNdx].name;
2802 filterModeGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, caseName.c_str(), "", gatherType, offsetSize, format, compareMode,
2803 tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, MaybeTextureSwizzle::createNoneTextureSwizzle(),
2804 minFilter, magFilter, LevelMode::NORMAL, 0, IVec3(64, 64, 3)));
2805 #ifndef CTS_USES_VULKANSC
2806 filterModeGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, "sparse_" + caseName, "", gatherType, offsetSize, format, compareMode,
2807 tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL, MaybeTextureSwizzle::createNoneTextureSwizzle(),
2808 minFilter, magFilter, LevelMode::NORMAL, 0, IVec3(64, 64, 3), 0, ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE));
2809 #endif // CTS_USES_VULKANSC
2814 TestCaseGroup* const baseLevelGroup = new TestCaseGroup(m_testCtx, "base_level", "");
2815 formatGroup->addChild(baseLevelGroup);
2817 for (int baseLevel = 1; baseLevel <= 2; baseLevel++)
2821 const std::string suffix;
2822 LevelMode levelMode;
2825 { "", LevelMode::NORMAL },
2826 #ifndef CTS_USES_VULKANSC
2827 { "_amd_bias", LevelMode::AMD_BIAS },
2828 { "_amd_lod", LevelMode::AMD_LOD },
2832 for (int modeIdx = 0; modeIdx < DE_LENGTH_OF_ARRAY(levelModes); ++modeIdx)
2834 const auto& mode = levelModes[modeIdx].levelMode;
2836 // Not supported for these sampler types.
2837 if (isDepthFormat(format) && mode != LevelMode::NORMAL)
2840 const string caseName = "level_" + de::toString(baseLevel) + levelModes[modeIdx].suffix;
2841 const tcu::Sampler::CompareMode compareMode = isDepthFormat(format) ? tcu::Sampler::COMPAREMODE_LESS : tcu::Sampler::COMPAREMODE_NONE;
2842 // The minFilter mode may need to be NEAREST_MIPMAP_NEAREST so the sampler creating code will not limit maxLod.
2843 const auto minFilter = ((mode == LevelMode::NORMAL) ? tcu::Sampler::NEAREST : tcu::Sampler::NEAREST_MIPMAP_NEAREST);
2844 baseLevelGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, caseName.c_str(), "", gatherType, offsetSize, format,
2845 compareMode, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2846 MaybeTextureSwizzle::createNoneTextureSwizzle(), minFilter, tcu::Sampler::NEAREST,
2847 mode, baseLevel, IVec3(64, 64, 3)));
2848 #ifndef CTS_USES_VULKANSC
2849 baseLevelGroup->addChild(makeTextureGatherCase(textureType, m_testCtx, "sparse_" + caseName, "", gatherType, offsetSize, format,
2850 compareMode, tcu::Sampler::REPEAT_GL, tcu::Sampler::REPEAT_GL,
2851 MaybeTextureSwizzle::createNoneTextureSwizzle(), minFilter, tcu::Sampler::NEAREST,
2852 mode, baseLevel, IVec3(64, 64, 3), 0, ShaderRenderCaseInstance::IMAGE_BACKING_MODE_SPARSE));
2853 #endif // CTS_USES_VULKANSC
2866 tcu::TestCaseGroup* createTextureGatherTests (tcu::TestContext& testCtx)
2868 return new TextureGatherTests(testCtx);