xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/texture/vktTextureMipmapTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 The Khronos Group Inc.
6  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
7  * Copyright 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Mipmapping tests.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktTextureMipmapTests.hpp"
27 
28 #include "deRandom.hpp"
29 #include "deString.h"
30 #include "gluShaderUtil.hpp"
31 #include "gluTextureTestUtil.hpp"
32 #include "tcuMatrix.hpp"
33 #include "tcuMatrixUtil.hpp"
34 #include "tcuPixelFormat.hpp"
35 #include "tcuTexLookupVerifier.hpp"
36 #include "tcuTextureUtil.hpp"
37 #include "tcuVectorUtil.hpp"
38 #include "tcuCommandLine.hpp"
39 #include "vkImageUtil.hpp"
40 #include "vkQueryUtil.hpp"
41 #include "vkImageWithMemory.hpp"
42 #include "vkBufferWithMemory.hpp"
43 #include "vkObjUtil.hpp"
44 #include "vkCmdUtil.hpp"
45 #include "vkBarrierUtil.hpp"
46 #include "vkBuilderUtil.hpp"
47 #include "vktTestGroupUtil.hpp"
48 #include "vktTextureTestUtil.hpp"
49 #include "vktCustomInstancesDevices.hpp"
50 
51 #include <memory>
52 
53 using namespace vk;
54 
55 namespace vkt
56 {
57 namespace texture
58 {
59 namespace
60 {
61 
62 using std::string;
63 using std::vector;
64 using tcu::IVec3;
65 using tcu::IVec4;
66 using tcu::Sampler;
67 using tcu::TestLog;
68 using tcu::TextureFormat;
69 using tcu::Vec2;
70 using tcu::Vec3;
71 using tcu::Vec4;
72 using namespace texture::util;
73 using namespace glu::TextureTestUtil;
74 
getMinLodForCell(int cellNdx)75 float getMinLodForCell(int cellNdx)
76 {
77     static const float s_values[] = {1.0f, 3.5f, 2.0f,  -2.0f, 0.0f, 3.0f, 10.0f, 4.8f,
78                                      5.8f, 5.7f, -1.9f, 4.0f,  6.5f, 7.1f, -1e10, 1000.f};
79     return s_values[cellNdx % DE_LENGTH_OF_ARRAY(s_values)];
80 }
81 
getMaxLodForCell(int cellNdx)82 float getMaxLodForCell(int cellNdx)
83 {
84     static const float s_values[] = {0.0f, 0.2f, 0.7f, 0.4f, 1.3f, 0.0f,  0.5f,    1.2f, -2.0f,
85                                      1.0f, 0.1f, 0.3f, 2.7f, 1.2f, 10.0f, -1000.f, 1e10f};
86     return s_values[cellNdx % DE_LENGTH_OF_ARRAY(s_values)];
87 }
88 
89 enum CoordType
90 {
91     COORDTYPE_BASIC,      //!< texCoord = translateScale(position).
92     COORDTYPE_BASIC_BIAS, //!< Like basic, but with bias values.
93     COORDTYPE_AFFINE,     //!< texCoord = translateScaleRotateShear(position).
94     COORDTYPE_PROJECTED,  //!< Projected coordinates, w != 1
95 
96     COORDTYPE_LAST
97 };
98 
99 struct TextureMipmapCommonTestCaseParameters
100 {
101     TextureMipmapCommonTestCaseParameters(void);
102     CoordType coordType;
103     const char *minFilterName;
104 };
105 
TextureMipmapCommonTestCaseParameters(void)106 TextureMipmapCommonTestCaseParameters::TextureMipmapCommonTestCaseParameters(void)
107     : coordType(COORDTYPE_BASIC)
108     , minFilterName(NULL)
109 {
110 }
111 
112 struct Texture2DMipmapTestCaseParameters : public Texture2DTestCaseParameters,
113                                            public TextureMipmapCommonTestCaseParameters
114 {
115 };
116 
117 struct TextureCubeMipmapTestCaseParameters : public TextureCubeTestCaseParameters,
118                                              public TextureMipmapCommonTestCaseParameters
119 {
120 };
121 
122 struct Texture3DMipmapTestCaseParameters : public Texture3DTestCaseParameters,
123                                            public TextureMipmapCommonTestCaseParameters
124 {
125 };
126 
127 // Texture2DMipmapTestInstance
128 class Texture2DMipmapTestInstance : public TestInstance
129 {
130 public:
131     typedef Texture2DMipmapTestCaseParameters ParameterType;
132 
133     Texture2DMipmapTestInstance(Context &context, const ParameterType &testParameters);
134     ~Texture2DMipmapTestInstance(void);
135 
136     virtual tcu::TestStatus iterate(void);
137 
138 private:
139     Texture2DMipmapTestInstance(const Texture2DMipmapTestInstance &other);
140     Texture2DMipmapTestInstance &operator=(const Texture2DMipmapTestInstance &other);
141 
142     const ParameterType m_testParameters;
143     TestTexture2DSp m_texture;
144     TextureRenderer m_renderer;
145 };
146 
Texture2DMipmapTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)147 Texture2DMipmapTestInstance::Texture2DMipmapTestInstance(Context &context,
148                                                          const Texture2DMipmapTestCaseParameters &testParameters)
149     : TestInstance(context)
150     , m_testParameters(testParameters)
151     , m_renderer(context, testParameters.sampleCount, testParameters.width * 4, testParameters.height * 4)
152 {
153     TCU_CHECK_INTERNAL(
154         !(m_testParameters.coordType == COORDTYPE_PROJECTED && m_testParameters.sampleCount != VK_SAMPLE_COUNT_1_BIT));
155 
156     m_texture = TestTexture2DSp(new pipeline::TestTexture2D(vk::mapVkFormat(m_testParameters.format),
157                                                             m_testParameters.width, m_testParameters.height));
158 
159     const int numLevels = deLog2Floor32(de::max(m_testParameters.width, m_testParameters.height)) + 1;
160 
161     // Fill texture with colored grid.
162     for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
163     {
164         const uint32_t step  = 0xff / (numLevels - 1);
165         const uint32_t inc   = deClamp32(step * levelNdx, 0x00, 0xff);
166         const uint32_t dec   = 0xff - inc;
167         const uint32_t rgb   = (inc << 16) | (dec << 8) | 0xff;
168         const uint32_t color = 0xff000000 | rgb;
169 
170         tcu::clear(m_texture->getLevel(levelNdx, 0), tcu::RGBA(color).toVec());
171     }
172 
173     // Upload texture data.
174     m_renderer.add2DTexture(m_texture, testParameters.aspectMask);
175 }
176 
~Texture2DMipmapTestInstance(void)177 Texture2DMipmapTestInstance::~Texture2DMipmapTestInstance(void)
178 {
179 }
180 
getBasicTexCoord2D(std::vector<float> & dst,int cellNdx)181 static void getBasicTexCoord2D(std::vector<float> &dst, int cellNdx)
182 {
183     static const struct
184     {
185         const Vec2 bottomLeft;
186         const Vec2 topRight;
187     } s_basicCoords[] = {
188         {Vec2(-0.1f, 0.1f), Vec2(0.8f, 1.0f)},     {Vec2(-0.3f, -0.6f), Vec2(0.7f, 0.4f)},
189         {Vec2(-0.3f, 0.6f), Vec2(0.7f, -0.9f)},    {Vec2(-0.8f, 0.6f), Vec2(0.7f, -0.9f)},
190 
191         {Vec2(-0.5f, -0.5f), Vec2(1.5f, 1.5f)},    {Vec2(1.0f, -1.0f), Vec2(-1.3f, 1.0f)},
192         {Vec2(1.2f, -1.0f), Vec2(-1.3f, 1.6f)},    {Vec2(2.2f, -1.1f), Vec2(-1.3f, 0.8f)},
193 
194         {Vec2(-1.5f, 1.6f), Vec2(1.7f, -1.4f)},    {Vec2(2.0f, 1.6f), Vec2(2.3f, -1.4f)},
195         {Vec2(1.3f, -2.6f), Vec2(-2.7f, 2.9f)},    {Vec2(-0.8f, -6.6f), Vec2(6.0f, -0.9f)},
196 
197         {Vec2(-8.0f, 9.0f), Vec2(8.3f, -7.0f)},    {Vec2(-16.0f, 10.0f), Vec2(18.3f, 24.0f)},
198         {Vec2(30.2f, 55.0f), Vec2(-24.3f, -1.6f)}, {Vec2(-33.2f, 64.1f), Vec2(32.1f, -64.1f)},
199     };
200 
201     DE_ASSERT(de::inBounds(cellNdx, 0, DE_LENGTH_OF_ARRAY(s_basicCoords)));
202 
203     const Vec2 &bottomLeft = s_basicCoords[cellNdx].bottomLeft;
204     const Vec2 &topRight   = s_basicCoords[cellNdx].topRight;
205 
206     computeQuadTexCoord2D(dst, bottomLeft, topRight);
207 }
208 
getBasicTexCoord2DImageViewMinLodIntTexCoord(std::vector<float> & dst)209 static void getBasicTexCoord2DImageViewMinLodIntTexCoord(std::vector<float> &dst)
210 {
211     computeQuadTexCoord2D(dst, Vec2(0.0f), Vec2(1.0f));
212 }
213 
getAffineTexCoord2D(std::vector<float> & dst,int cellNdx)214 static void getAffineTexCoord2D(std::vector<float> &dst, int cellNdx)
215 {
216     // Use basic coords as base.
217     getBasicTexCoord2D(dst, cellNdx);
218 
219     // Rotate based on cell index.
220     const float angle         = 2.0f * DE_PI * ((float)cellNdx / 16.0f);
221     const tcu::Mat2 rotMatrix = tcu::rotationMatrix(angle);
222 
223     // Second and third row are sheared.
224     const float shearX          = de::inRange(cellNdx, 4, 11) ? (float)(15 - cellNdx) / 16.0f : 0.0f;
225     const tcu::Mat2 shearMatrix = tcu::shearMatrix(tcu::Vec2(shearX, 0.0f));
226 
227     const tcu::Mat2 transform = rotMatrix * shearMatrix;
228     const Vec2 p0             = transform * Vec2(dst[0], dst[1]);
229     const Vec2 p1             = transform * Vec2(dst[2], dst[3]);
230     const Vec2 p2             = transform * Vec2(dst[4], dst[5]);
231     const Vec2 p3             = transform * Vec2(dst[6], dst[7]);
232 
233     dst[0] = p0.x();
234     dst[1] = p0.y();
235     dst[2] = p1.x();
236     dst[3] = p1.y();
237     dst[4] = p2.x();
238     dst[5] = p2.y();
239     dst[6] = p3.x();
240     dst[7] = p3.y();
241 }
242 
iterate(void)243 tcu::TestStatus Texture2DMipmapTestInstance::iterate(void)
244 {
245     const Sampler::FilterMode magFilter = Sampler::NEAREST;
246     const int viewportWidth             = m_renderer.getRenderWidth();
247     const int viewportHeight            = m_renderer.getRenderHeight();
248 
249     ReferenceParams refParams(TEXTURETYPE_2D);
250     vector<float> texCoord;
251 
252     const bool isProjected = m_testParameters.coordType == COORDTYPE_PROJECTED;
253     const bool useLodBias  = m_testParameters.coordType == COORDTYPE_BASIC_BIAS;
254 
255     tcu::Surface renderedFrame(viewportWidth, viewportHeight);
256 
257     // Viewport is divided into 4x4 grid.
258     const int gridWidth  = 4;
259     const int gridHeight = 4;
260     const int cellWidth  = viewportWidth / gridWidth;
261     const int cellHeight = viewportHeight / gridHeight;
262 
263     // Sampling parameters.
264     refParams.sampler =
265         util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, magFilter);
266     refParams.samplerType = getSamplerType(vk::mapVkFormat(m_testParameters.format));
267     refParams.flags   = (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
268     refParams.lodMode = LODMODE_EXACT; // Use ideal lod.
269 
270     // Bias values.
271     static const float s_bias[] = {1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f};
272 
273     // Projection values.
274     static const Vec4 s_projections[] = {Vec4(1.2f, 1.0f, 0.7f, 1.0f), Vec4(1.3f, 0.8f, 0.6f, 2.0f),
275                                          Vec4(0.8f, 1.0f, 1.7f, 0.6f), Vec4(1.2f, 1.0f, 1.7f, 1.5f)};
276 
277     // Render cells.
278     for (int gridY = 0; gridY < gridHeight; gridY++)
279     {
280         for (int gridX = 0; gridX < gridWidth; gridX++)
281         {
282             const int curX    = cellWidth * gridX;
283             const int curY    = cellHeight * gridY;
284             const int curW    = gridX + 1 == gridWidth ? (viewportWidth - curX) : cellWidth;
285             const int curH    = gridY + 1 == gridHeight ? (viewportHeight - curY) : cellHeight;
286             const int cellNdx = gridY * gridWidth + gridX;
287 
288             // Compute texcoord.
289             switch (m_testParameters.coordType)
290             {
291             case COORDTYPE_BASIC_BIAS: // Fall-through.
292             case COORDTYPE_PROJECTED:
293             case COORDTYPE_BASIC:
294                 getBasicTexCoord2D(texCoord, cellNdx);
295                 break;
296             case COORDTYPE_AFFINE:
297                 getAffineTexCoord2D(texCoord, cellNdx);
298                 break;
299             default:
300                 DE_ASSERT(false);
301             }
302 
303             if (isProjected)
304                 refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
305 
306             if (useLodBias)
307                 refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
308 
309             m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
310             m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
311         }
312     }
313 
314     // Compare and log.
315     {
316         const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
317         const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
318         const bool isTrilinear = m_testParameters.minFilter == Sampler::NEAREST_MIPMAP_LINEAR ||
319                                  m_testParameters.minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
320         tcu::Surface referenceFrame(viewportWidth, viewportHeight);
321         tcu::Surface errorMask(viewportWidth, viewportHeight);
322         tcu::LookupPrecision lookupPrec;
323         tcu::LodPrecision lodPrec;
324         int numFailedPixels = 0;
325 
326         lookupPrec.coordBits = tcu::IVec3(20, 20, 0);
327         lookupPrec.uvwBits   = tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
328         lookupPrec.colorThreshold =
329             tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
330         lookupPrec.colorMask = getCompareMask(pixelFormat);
331         lodPrec.derivateBits = 10;
332         lodPrec.lodBits      = isProjected ? 6 : 8;
333 
334         for (int gridY = 0; gridY < gridHeight; gridY++)
335         {
336             for (int gridX = 0; gridX < gridWidth; gridX++)
337             {
338                 const int curX    = cellWidth * gridX;
339                 const int curY    = cellHeight * gridY;
340                 const int curW    = gridX + 1 == gridWidth ? (viewportWidth - curX) : cellWidth;
341                 const int curH    = gridY + 1 == gridHeight ? (viewportHeight - curY) : cellHeight;
342                 const int cellNdx = gridY * gridWidth + gridX;
343 
344                 // Compute texcoord.
345                 switch (m_testParameters.coordType)
346                 {
347                 case COORDTYPE_BASIC_BIAS: // Fall-through.
348                 case COORDTYPE_PROJECTED:
349                 case COORDTYPE_BASIC:
350                     getBasicTexCoord2D(texCoord, cellNdx);
351                     break;
352                 case COORDTYPE_AFFINE:
353                     getAffineTexCoord2D(texCoord, cellNdx);
354                     break;
355                 default:
356                     DE_ASSERT(false);
357                 }
358 
359                 if (isProjected)
360                     refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
361 
362                 if (useLodBias)
363                     refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
364 
365                 // Render ideal result
366                 sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
367                               m_texture->getTexture(), &texCoord[0], refParams);
368 
369                 // Compare this cell
370                 numFailedPixels += computeTextureLookupDiff(
371                     tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
372                     tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
373                     tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getTexture(),
374                     &texCoord[0], refParams, lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
375             }
376         }
377 
378         if (numFailedPixels > 0)
379             m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found "
380                                                 << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
381 
382         m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
383                                             << TestLog::Image("Rendered", "Rendered image", renderedFrame);
384 
385         if (numFailedPixels > 0)
386         {
387             m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
388                                                 << TestLog::Image("ErrorMask", "Error mask", errorMask);
389         }
390 
391         m_context.getTestContext().getLog() << TestLog::EndImageSet;
392 
393         {
394             const bool isOk = numFailedPixels == 0;
395             return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
396         }
397     }
398 }
399 
400 // TextureCubeMipmapTestInstance
401 class TextureCubeMipmapTestInstance : public TestInstance
402 {
403 public:
404     typedef TextureCubeMipmapTestCaseParameters ParameterType;
405 
406     TextureCubeMipmapTestInstance(Context &context, const ParameterType &testParameters);
407     ~TextureCubeMipmapTestInstance(void);
408 
409     virtual tcu::TestStatus iterate(void);
410 
411 private:
412     TextureCubeMipmapTestInstance(const TextureCubeMipmapTestInstance &other);
413     TextureCubeMipmapTestInstance &operator=(const TextureCubeMipmapTestInstance &other);
414 
415     const ParameterType m_testParameters;
416     TestTextureCubeSp m_texture;
417     TextureRenderer m_renderer;
418 };
419 
TextureCubeMipmapTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)420 TextureCubeMipmapTestInstance::TextureCubeMipmapTestInstance(Context &context,
421                                                              const TextureCubeMipmapTestCaseParameters &testParameters)
422     : TestInstance(context)
423     , m_testParameters(testParameters)
424     , m_renderer(context, m_testParameters.sampleCount, m_testParameters.size * 2, m_testParameters.size * 2)
425 {
426     TCU_CHECK_INTERNAL(
427         !(m_testParameters.coordType == COORDTYPE_PROJECTED && m_testParameters.sampleCount != VK_SAMPLE_COUNT_1_BIT));
428 
429     m_texture = TestTextureCubeSp(
430         new pipeline::TestTextureCube(vk::mapVkFormat(m_testParameters.format), m_testParameters.size));
431 
432     const int numLevels = deLog2Floor32(m_testParameters.size) + 1;
433 
434     // Fill texture with colored grid.
435     for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
436     {
437         for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
438         {
439             const uint32_t step = 0xff / (numLevels - 1);
440             const uint32_t inc  = deClamp32(step * levelNdx, 0x00, 0xff);
441             const uint32_t dec  = 0xff - inc;
442             uint32_t rgb        = 0;
443 
444             switch (faceNdx)
445             {
446             case 0:
447                 rgb = (inc << 16) | (dec << 8) | 255;
448                 break;
449             case 1:
450                 rgb = (255 << 16) | (inc << 8) | dec;
451                 break;
452             case 2:
453                 rgb = (dec << 16) | (255 << 8) | inc;
454                 break;
455             case 3:
456                 rgb = (dec << 16) | (inc << 8) | 255;
457                 break;
458             case 4:
459                 rgb = (255 << 16) | (dec << 8) | inc;
460                 break;
461             case 5:
462                 rgb = (inc << 16) | (255 << 8) | dec;
463                 break;
464             }
465 
466             const uint32_t color = 0xff000000 | rgb;
467             tcu::clear(m_texture->getLevel(levelNdx, (tcu::CubeFace)faceNdx), tcu::RGBA(color).toVec());
468         }
469     }
470 
471     m_renderer.addCubeTexture(m_texture, testParameters.aspectMask);
472 }
473 
~TextureCubeMipmapTestInstance(void)474 TextureCubeMipmapTestInstance::~TextureCubeMipmapTestInstance(void)
475 {
476 }
477 
randomPartition(vector<IVec4> & dst,de::Random & rnd,int x,int y,int width,int height)478 static void randomPartition(vector<IVec4> &dst, de::Random &rnd, int x, int y, int width, int height)
479 {
480     const int minWidth  = 8;
481     const int minHeight = 8;
482 
483     const bool partition  = rnd.getFloat() > 0.4f;
484     const bool partitionX = partition && width > minWidth && rnd.getBool();
485     const bool partitionY = partition && height > minHeight && !partitionX;
486 
487     if (partitionX)
488     {
489         const int split = width / 2 + rnd.getInt(-width / 4, +width / 4);
490         randomPartition(dst, rnd, x, y, split, height);
491         randomPartition(dst, rnd, x + split, y, width - split, height);
492     }
493     else if (partitionY)
494     {
495         const int split = height / 2 + rnd.getInt(-height / 4, +height / 4);
496         randomPartition(dst, rnd, x, y, width, split);
497         randomPartition(dst, rnd, x, y + split, width, height - split);
498     }
499     else
500         dst.push_back(IVec4(x, y, width, height));
501 }
502 
computeGridLayout(vector<IVec4> & dst,int width,int height)503 static void computeGridLayout(vector<IVec4> &dst, int width, int height)
504 {
505     de::Random rnd(7);
506     randomPartition(dst, rnd, 0, 0, width, height);
507 }
508 
iterate(void)509 tcu::TestStatus TextureCubeMipmapTestInstance::iterate(void)
510 {
511     const int viewportWidth  = m_renderer.getRenderWidth();
512     const int viewportHeight = m_renderer.getRenderHeight();
513 
514     const bool isProjected = m_testParameters.coordType == COORDTYPE_PROJECTED;
515     const bool useLodBias  = m_testParameters.coordType == COORDTYPE_BASIC_BIAS;
516 
517     ReferenceParams refParams(TEXTURETYPE_CUBE);
518     vector<float> texCoord;
519     tcu::Surface renderedFrame(viewportWidth, viewportHeight);
520 
521     refParams.sampler = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter,
522                                             m_testParameters.magFilter);
523     refParams.samplerType = getSamplerType(vk::mapVkFormat(m_testParameters.format));
524     refParams.flags   = (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
525     refParams.lodMode = LODMODE_EXACT; // Use ideal lod.
526 
527     // Compute grid.
528     vector<IVec4> gridLayout;
529     computeGridLayout(gridLayout, viewportWidth, viewportHeight);
530 
531     // Bias values.
532     static const float s_bias[] = {1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f};
533 
534     // Projection values \note Less agressive than in 2D case due to smaller quads.
535     static const Vec4 s_projections[] = {Vec4(1.2f, 1.0f, 0.7f, 1.0f), Vec4(1.3f, 0.8f, 0.6f, 1.1f),
536                                          Vec4(0.8f, 1.0f, 1.2f, 0.8f), Vec4(1.2f, 1.0f, 1.3f, 0.9f)};
537 
538     // Render with GL
539     for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
540     {
541         const float curX             = (float)gridLayout[cellNdx].x();
542         const float curY             = (float)gridLayout[cellNdx].y();
543         const float curW             = (float)gridLayout[cellNdx].z();
544         const float curH             = (float)gridLayout[cellNdx].w();
545         const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
546 
547         DE_ASSERT(m_testParameters.coordType != COORDTYPE_AFFINE); // Not supported.
548         computeQuadTexCoordCube(texCoord, cubeFace);
549 
550         if (isProjected)
551         {
552             refParams.flags |= ReferenceParams::PROJECTED;
553             refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
554         }
555 
556         if (useLodBias)
557         {
558             refParams.flags |= ReferenceParams::USE_BIAS;
559             refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
560         }
561 
562         // Render
563         m_renderer.setViewport(curX, curY, curW, curH);
564         m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
565     }
566 
567     // Render reference and compare
568     {
569         const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
570         const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
571         tcu::Surface referenceFrame(viewportWidth, viewportHeight);
572         tcu::Surface errorMask(viewportWidth, viewportHeight);
573         int numFailedPixels = 0;
574         tcu::LookupPrecision lookupPrec;
575         tcu::LodPrecision lodPrec;
576 
577         // Params for rendering reference
578         refParams.sampler                 = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT,
579                                                                 m_testParameters.minFilter, m_testParameters.magFilter);
580         refParams.sampler.seamlessCubeMap = true;
581         refParams.lodMode                 = LODMODE_EXACT;
582 
583         // Comparison parameters
584         lookupPrec.colorMask      = getCompareMask(pixelFormat);
585         lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - 2, tcu::IVec4(0)));
586         lookupPrec.coordBits      = isProjected ? tcu::IVec3(8) : tcu::IVec3(10);
587         lookupPrec.uvwBits        = tcu::IVec3(5, 5, 0);
588         lodPrec.derivateBits      = 10;
589         lodPrec.lodBits           = isProjected ? 3 : 6;
590 
591         for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
592         {
593             const int curX               = gridLayout[cellNdx].x();
594             const int curY               = gridLayout[cellNdx].y();
595             const int curW               = gridLayout[cellNdx].z();
596             const int curH               = gridLayout[cellNdx].w();
597             const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
598 
599             DE_ASSERT(m_testParameters.coordType != COORDTYPE_AFFINE); // Not supported.
600             computeQuadTexCoordCube(texCoord, cubeFace);
601 
602             if (isProjected)
603             {
604                 refParams.flags |= ReferenceParams::PROJECTED;
605                 refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
606             }
607 
608             if (useLodBias)
609             {
610                 refParams.flags |= ReferenceParams::USE_BIAS;
611                 refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
612             }
613 
614             // Render ideal reference.
615             {
616                 tcu::SurfaceAccess idealDst(referenceFrame, pixelFormat, curX, curY, curW, curH);
617                 sampleTexture(idealDst, m_texture->getTexture(), &texCoord[0], refParams);
618             }
619 
620             // Compare this cell
621             numFailedPixels += computeTextureLookupDiff(
622                 tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
623                 tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
624                 tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getTexture(), &texCoord[0],
625                 refParams, lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
626         }
627 
628         if (numFailedPixels > 0)
629         {
630             m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found "
631                                                 << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
632         }
633 
634         m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
635                                             << TestLog::Image("Rendered", "Rendered image", renderedFrame);
636 
637         if (numFailedPixels > 0)
638         {
639             m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
640                                                 << TestLog::Image("ErrorMask", "Error mask", errorMask);
641         }
642 
643         m_context.getTestContext().getLog() << TestLog::EndImageSet;
644 
645         {
646             const bool isOk = numFailedPixels == 0;
647             return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
648         }
649     }
650 }
651 
652 // Texture3DMipmapTestInstance
653 class Texture3DMipmapTestInstance : public TestInstance
654 {
655 public:
656     typedef Texture3DMipmapTestCaseParameters ParameterType;
657 
658     Texture3DMipmapTestInstance(Context &context, const ParameterType &testParameters);
659     ~Texture3DMipmapTestInstance(void);
660 
661     virtual tcu::TestStatus iterate(void);
662 
663 private:
664     Texture3DMipmapTestInstance(const Texture3DMipmapTestInstance &other);
665     Texture3DMipmapTestInstance &operator=(const Texture3DMipmapTestInstance &other);
666 
667     const ParameterType m_testParameters;
668     TestTexture3DSp m_texture;
669     TextureRenderer m_renderer;
670 };
671 
Texture3DMipmapTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)672 Texture3DMipmapTestInstance::Texture3DMipmapTestInstance(Context &context,
673                                                          const Texture3DMipmapTestCaseParameters &testParameters)
674     : TestInstance(context)
675     , m_testParameters(testParameters)
676     , m_renderer(context, testParameters.sampleCount, testParameters.width * 4, testParameters.height * 4)
677 {
678     TCU_CHECK_INTERNAL(
679         !(m_testParameters.coordType == COORDTYPE_PROJECTED && m_testParameters.sampleCount != VK_SAMPLE_COUNT_1_BIT));
680 
681     const tcu::TextureFormat &texFmt = mapVkFormat(testParameters.format);
682     tcu::TextureFormatInfo fmtInfo   = tcu::getTextureFormatInfo(texFmt);
683     const tcu::Vec4 &cScale          = fmtInfo.lookupScale;
684     const tcu::Vec4 &cBias           = fmtInfo.lookupBias;
685     const int numLevels =
686         deLog2Floor32(de::max(de::max(testParameters.width, testParameters.height), testParameters.depth)) + 1;
687 
688     m_texture =
689         TestTexture3DSp(new pipeline::TestTexture3D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width,
690                                                     m_testParameters.height, m_testParameters.depth));
691 
692     // Fill texture with colored grid.
693     for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
694     {
695         const uint32_t step  = 0xff / (numLevels - 1);
696         const uint32_t inc   = deClamp32(step * levelNdx, 0x00, 0xff);
697         const uint32_t dec   = 0xff - inc;
698         const uint32_t rgb   = (0xff << 16) | (dec << 8) | inc;
699         const uint32_t color = 0xff000000 | rgb;
700 
701         tcu::clear(m_texture->getLevel(levelNdx, 0), tcu::RGBA(color).toVec() * cScale + cBias);
702     }
703 
704     m_renderer.add3DTexture(m_texture, testParameters.aspectMask);
705 }
706 
~Texture3DMipmapTestInstance(void)707 Texture3DMipmapTestInstance::~Texture3DMipmapTestInstance(void)
708 {
709 }
710 
getBasicTexCoord3D(std::vector<float> & dst,int cellNdx)711 static void getBasicTexCoord3D(std::vector<float> &dst, int cellNdx)
712 {
713     static const struct
714     {
715         const float sScale;
716         const float sBias;
717         const float tScale;
718         const float tBias;
719         const float rScale;
720         const float rBias;
721     } s_params[] = {//        sScale    sBias    tScale    tBias    rScale    rBias
722                     {0.9f, -0.1f, 0.7f, 0.3f, 0.8f, 0.9f},    {1.2f, -0.1f, 1.1f, 0.3f, 1.0f, 0.9f},
723                     {1.5f, 0.7f, 0.9f, -0.3f, 1.1f, 0.1f},    {1.2f, 0.7f, -2.3f, -0.3f, 1.1f, 0.2f},
724                     {1.1f, 0.8f, -1.3f, -0.3f, 2.9f, 0.9f},   {3.4f, 0.8f, 4.0f, 0.0f, -3.3f, -1.0f},
725                     {-3.4f, -0.1f, -4.0f, 0.0f, -5.1f, 1.0f}, {-4.0f, -0.1f, 3.4f, 0.1f, 5.7f, 0.0f},
726                     {-5.6f, 0.0f, 0.5f, 1.2f, 3.9f, 4.0f},    {5.0f, -2.0f, 3.1f, 1.2f, 5.1f, 0.2f},
727                     {2.5f, -2.0f, 6.3f, 3.0f, 5.1f, 0.2f},    {-8.3f, 0.0f, 7.1f, 3.0f, 2.0f, 0.2f},
728                     {3.8f, 0.0f, 9.7f, 1.0f, 7.0f, 0.7f},     {13.3f, 0.0f, 7.1f, 3.0f, 2.0f, 0.2f},
729                     {16.0f, 8.0f, 12.7f, 1.0f, 17.1f, 0.7f},  {15.3f, 0.0f, 20.1f, 3.0f, 33.0f, 3.2f}};
730 
731     const float sScale = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].sScale;
732     const float sBias  = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].sBias;
733     const float tScale = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].tScale;
734     const float tBias  = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].tBias;
735     const float rScale = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].rScale;
736     const float rBias  = s_params[cellNdx % DE_LENGTH_OF_ARRAY(s_params)].rBias;
737 
738     dst.resize(3 * 4);
739 
740     dst[0]  = sBias;
741     dst[1]  = tBias;
742     dst[2]  = rBias;
743     dst[3]  = sBias;
744     dst[4]  = tBias + tScale;
745     dst[5]  = rBias + rScale * 0.5f;
746     dst[6]  = sBias + sScale;
747     dst[7]  = tBias;
748     dst[8]  = rBias + rScale * 0.5f;
749     dst[9]  = sBias + sScale;
750     dst[10] = tBias + tScale;
751     dst[11] = rBias + rScale;
752 }
753 
getBasicTexCoord3DImageViewMinlodIntTexCoord(std::vector<float> & dst)754 static void getBasicTexCoord3DImageViewMinlodIntTexCoord(std::vector<float> &dst)
755 {
756     const float sScale = 1.0f;
757     const float sBias  = 0.0f;
758     const float tScale = 1.0f;
759     const float tBias  = 0.0f;
760     const float rScale = 1.0f;
761     const float rBias  = 0.0f;
762 
763     dst.resize(3 * 4);
764 
765     dst[0]  = sBias;
766     dst[1]  = tBias;
767     dst[2]  = rBias;
768     dst[3]  = sBias;
769     dst[4]  = tBias + tScale;
770     dst[5]  = rBias + rScale * 0.5f;
771     dst[6]  = sBias + sScale;
772     dst[7]  = tBias;
773     dst[8]  = rBias + rScale * 0.5f;
774     dst[9]  = sBias + sScale;
775     dst[10] = tBias + tScale;
776     dst[11] = rBias + rScale;
777 }
778 
getAffineTexCoord3D(std::vector<float> & dst,int cellNdx)779 static void getAffineTexCoord3D(std::vector<float> &dst, int cellNdx)
780 {
781     // Use basic coords as base.
782     getBasicTexCoord3D(dst, cellNdx);
783 
784     // Rotate based on cell index.
785     const float angleX        = 0.0f + 2.0f * DE_PI * ((float)cellNdx / 16.0f);
786     const float angleY        = 1.0f + 2.0f * DE_PI * ((float)cellNdx / 32.0f);
787     const tcu::Mat3 rotMatrix = tcu::rotationMatrixX(angleX) * tcu::rotationMatrixY(angleY);
788 
789     const Vec3 p0 = rotMatrix * Vec3(dst[0], dst[1], dst[2]);
790     const Vec3 p1 = rotMatrix * Vec3(dst[3], dst[4], dst[5]);
791     const Vec3 p2 = rotMatrix * Vec3(dst[6], dst[7], dst[8]);
792     const Vec3 p3 = rotMatrix * Vec3(dst[9], dst[10], dst[11]);
793 
794     dst[0]  = p0.x();
795     dst[1]  = p0.y();
796     dst[2]  = p0.z();
797     dst[3]  = p1.x();
798     dst[4]  = p1.y();
799     dst[5]  = p1.z();
800     dst[6]  = p2.x();
801     dst[7]  = p2.y();
802     dst[8]  = p2.z();
803     dst[9]  = p3.x();
804     dst[10] = p3.y();
805     dst[11] = p3.z();
806 }
807 
iterate(void)808 tcu::TestStatus Texture3DMipmapTestInstance::iterate(void)
809 {
810     const tcu::TextureFormat &texFmt     = m_texture->getTextureFormat();
811     const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
812     const Sampler::FilterMode magFilter  = Sampler::NEAREST;
813     const int viewportWidth              = m_renderer.getRenderWidth();
814     const int viewportHeight             = m_renderer.getRenderHeight();
815 
816     const bool isProjected = m_testParameters.coordType == COORDTYPE_PROJECTED;
817     const bool useLodBias  = m_testParameters.coordType == COORDTYPE_BASIC_BIAS;
818 
819     // Viewport is divided into 4x4 grid.
820     const int gridWidth  = 4;
821     const int gridHeight = 4;
822     const int cellWidth  = viewportWidth / gridWidth;
823     const int cellHeight = viewportHeight / gridHeight;
824 
825     ReferenceParams refParams(TEXTURETYPE_3D);
826 
827     tcu::Surface renderedFrame(viewportWidth, viewportHeight);
828     vector<float> texCoord;
829 
830     // Sampling parameters.
831     refParams.sampler =
832         util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter, magFilter);
833     refParams.samplerType = getSamplerType(texFmt);
834 
835     refParams.colorBias  = fmtInfo.lookupBias;
836     refParams.colorScale = fmtInfo.lookupScale;
837     refParams.flags = (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
838 
839     // Bias values.
840     static const float s_bias[] = {1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f};
841 
842     // Projection values.
843     static const Vec4 s_projections[] = {Vec4(1.2f, 1.0f, 0.7f, 1.0f), Vec4(1.3f, 0.8f, 0.6f, 2.0f),
844                                          Vec4(0.8f, 1.0f, 1.7f, 0.6f), Vec4(1.2f, 1.0f, 1.7f, 1.5f)};
845 
846     // Render cells.
847     for (int gridY = 0; gridY < gridHeight; gridY++)
848     {
849         for (int gridX = 0; gridX < gridWidth; gridX++)
850         {
851             const int curX    = cellWidth * gridX;
852             const int curY    = cellHeight * gridY;
853             const int curW    = gridX + 1 == gridWidth ? (viewportWidth - curX) : cellWidth;
854             const int curH    = gridY + 1 == gridHeight ? (viewportHeight - curY) : cellHeight;
855             const int cellNdx = gridY * gridWidth + gridX;
856 
857             // Compute texcoord.
858             switch (m_testParameters.coordType)
859             {
860             case COORDTYPE_BASIC_BIAS: // Fall-through.
861             case COORDTYPE_PROJECTED:
862             case COORDTYPE_BASIC:
863                 getBasicTexCoord3D(texCoord, cellNdx);
864                 break;
865             case COORDTYPE_AFFINE:
866                 getAffineTexCoord3D(texCoord, cellNdx);
867                 break;
868             default:
869                 DE_ASSERT(false);
870             }
871 
872             // Set projection.
873             if (isProjected)
874                 refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
875 
876             // Set LOD bias.
877             if (useLodBias)
878                 refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
879 
880             m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
881             m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
882         }
883     }
884 
885     // Compare and log
886     {
887         const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
888         const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
889         const bool isTrilinear = m_testParameters.minFilter == Sampler::NEAREST_MIPMAP_LINEAR ||
890                                  m_testParameters.minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
891         tcu::Surface referenceFrame(viewportWidth, viewportHeight);
892         tcu::Surface errorMask(viewportWidth, viewportHeight);
893         tcu::LookupPrecision lookupPrec;
894         tcu::LodPrecision lodPrec;
895         int numFailedPixels = 0;
896 
897         lookupPrec.coordBits = tcu::IVec3(20, 20, 20);
898         lookupPrec.uvwBits   = tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored.
899         lookupPrec.colorThreshold =
900             tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
901         lookupPrec.colorMask = getCompareMask(pixelFormat);
902         lodPrec.derivateBits = 10;
903         lodPrec.lodBits      = isProjected ? 6 : 8;
904 
905         for (int gridY = 0; gridY < gridHeight; gridY++)
906         {
907             for (int gridX = 0; gridX < gridWidth; gridX++)
908             {
909                 const int curX    = cellWidth * gridX;
910                 const int curY    = cellHeight * gridY;
911                 const int curW    = gridX + 1 == gridWidth ? (viewportWidth - curX) : cellWidth;
912                 const int curH    = gridY + 1 == gridHeight ? (viewportHeight - curY) : cellHeight;
913                 const int cellNdx = gridY * gridWidth + gridX;
914 
915                 switch (m_testParameters.coordType)
916                 {
917                 case COORDTYPE_BASIC_BIAS: // Fall-through.
918                 case COORDTYPE_PROJECTED:
919                 case COORDTYPE_BASIC:
920                     getBasicTexCoord3D(texCoord, cellNdx);
921                     break;
922                 case COORDTYPE_AFFINE:
923                     getAffineTexCoord3D(texCoord, cellNdx);
924                     break;
925                 default:
926                     DE_ASSERT(false);
927                 }
928 
929                 if (isProjected)
930                     refParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
931 
932                 if (useLodBias)
933                     refParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
934 
935                 // Render ideal result
936                 sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
937                               m_texture->getTexture(), &texCoord[0], refParams);
938 
939                 // Compare this cell
940                 numFailedPixels += computeTextureLookupDiff(
941                     tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
942                     tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
943                     tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getTexture(),
944                     &texCoord[0], refParams, lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
945             }
946         }
947 
948         if (numFailedPixels > 0)
949             m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found "
950                                                 << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
951 
952         m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
953                                             << TestLog::Image("Rendered", "Rendered image", renderedFrame);
954 
955         if (numFailedPixels > 0)
956         {
957             m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
958                                                 << TestLog::Image("ErrorMask", "Error mask", errorMask);
959         }
960 
961         m_context.getTestContext().getLog() << TestLog::EndImageSet;
962 
963         {
964             const bool isOk = numFailedPixels == 0;
965             return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
966         }
967     }
968 }
969 
970 // Texture2DLodControlTestInstance
971 class Texture2DLodControlTestInstance : public TestInstance
972 {
973 public:
974     typedef Texture2DMipmapTestCaseParameters ParameterType;
975 
976     Texture2DLodControlTestInstance(Context &context, const ParameterType &testParameters);
977     ~Texture2DLodControlTestInstance(void);
978 
979     virtual tcu::TestStatus iterate(void);
980 
981 protected:
982     virtual void getReferenceParams(ReferenceParams &params, int cellNdx) = 0;
983 
984     const int m_texWidth;
985     const int m_texHeight;
986 
987 private:
988     Texture2DLodControlTestInstance(const Texture2DLodControlTestInstance &other);
989     Texture2DLodControlTestInstance &operator=(const Texture2DLodControlTestInstance &other);
990 
991     const ParameterType m_testParameters;
992     tcu::Sampler::FilterMode m_minFilter;
993     TestTexture2DSp m_texture;
994     TextureRenderer m_renderer;
995 };
996 
Texture2DLodControlTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)997 Texture2DLodControlTestInstance::Texture2DLodControlTestInstance(
998     Context &context, const Texture2DMipmapTestCaseParameters &testParameters)
999     : TestInstance(context)
1000     , m_texWidth(64)  //64
1001     , m_texHeight(64) //64
1002     , m_testParameters(testParameters)
1003     , m_minFilter(testParameters.minFilter)
1004     , m_texture(DE_NULL)
1005     , m_renderer(context, testParameters.sampleCount, m_texWidth * 4, m_texHeight * 4, vk::makeComponentMappingRGBA(),
1006                  testParameters.testType > util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD,
1007                  testParameters.testType >= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD)
1008 {
1009     const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1010     const int numLevels   = deLog2Floor32(de::max(m_texWidth, m_texHeight)) + 1;
1011 
1012     m_texture = TestTexture2DSp(new pipeline::TestTexture2D(vk::mapVkFormat(format), m_texWidth, m_texHeight));
1013 
1014     // Fill texture with colored grid.
1015     for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1016     {
1017         const uint32_t step  = 0xff / (numLevels - 1);
1018         const uint32_t inc   = deClamp32(step * levelNdx, 0x00, 0xff);
1019         const uint32_t dec   = 0xff - inc;
1020         const uint32_t rgb   = (inc << 16) | (dec << 8) | 0xff;
1021         const uint32_t color = 0xff000000 | rgb;
1022 
1023         tcu::clear(m_texture->getLevel(levelNdx, 0), tcu::RGBA(color).toVec());
1024     }
1025 
1026     m_renderer.add2DTexture(m_texture, testParameters.aspectMask);
1027 }
1028 
~Texture2DLodControlTestInstance(void)1029 Texture2DLodControlTestInstance::~Texture2DLodControlTestInstance(void)
1030 {
1031 }
1032 
iterate(void)1033 tcu::TestStatus Texture2DLodControlTestInstance::iterate(void)
1034 {
1035     const tcu::Sampler::WrapMode wrapS       = Sampler::REPEAT_GL;
1036     const tcu::Sampler::WrapMode wrapT       = Sampler::REPEAT_GL;
1037     const tcu::Sampler::FilterMode magFilter = Sampler::NEAREST;
1038 
1039     const tcu::Texture2D &refTexture = m_texture->getTexture();
1040 
1041     const int viewportWidth  = m_renderer.getRenderWidth();
1042     const int viewportHeight = m_renderer.getRenderHeight();
1043 
1044     tcu::Sampler sampler = util::createSampler(wrapS, wrapT, m_minFilter, magFilter);
1045 
1046     ReferenceParams refParams(TEXTURETYPE_2D, sampler);
1047     vector<float> texCoord;
1048     tcu::Surface renderedFrame(viewportWidth, viewportHeight);
1049 
1050     // Viewport is divided into 4x4 grid.
1051     const int gridWidth  = 4;
1052     const int gridHeight = 4;
1053     const int cellWidth  = viewportWidth / gridWidth;
1054     const int cellHeight = viewportHeight / gridHeight;
1055 
1056     refParams.maxLevel = deLog2Floor32(de::max(m_texWidth, m_texHeight));
1057 
1058     // Render cells.
1059     for (int gridY = 0; gridY < gridHeight; gridY++)
1060     {
1061         for (int gridX = 0; gridX < gridWidth; gridX++)
1062         {
1063             const int curX    = cellWidth * gridX;
1064             const int curY    = cellHeight * gridY;
1065             const int curW    = gridX + 1 == gridWidth ? (viewportWidth - curX) : cellWidth;
1066             const int curH    = gridY + 1 == gridHeight ? (viewportHeight - curY) : cellHeight;
1067             const int cellNdx = gridY * gridWidth + gridX;
1068 
1069             getReferenceParams(refParams, cellNdx);
1070 
1071             // Compute texcoord.
1072             getBasicTexCoord2D(texCoord, cellNdx);
1073             // Render
1074             m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
1075             m_renderer.getTextureBinding(0)->updateTextureViewMipLevels(refParams.baseLevel, refParams.maxLevel,
1076                                                                         refParams.imageViewMinLod);
1077             m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
1078         }
1079     }
1080 
1081     // Compare and log.
1082     {
1083         const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1084         const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
1085         const bool isTrilinear =
1086             m_minFilter == Sampler::NEAREST_MIPMAP_LINEAR || m_minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
1087         tcu::LookupPrecision lookupPrec;
1088         tcu::LodPrecision lodPrec;
1089 
1090         lookupPrec.coordBits = tcu::IVec3(20, 20, 0);
1091         lookupPrec.uvwBits   = tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
1092         lookupPrec.colorThreshold =
1093             tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
1094         lookupPrec.colorMask = getCompareMask(pixelFormat);
1095         lodPrec.derivateBits = 10;
1096         lodPrec.lodBits      = 8;
1097 
1098         auto compareAndLogImages = [&](tcu::ImageViewMinLodMode imageViewLodMode = tcu::IMAGEVIEWMINLODMODE_PREFERRED)
1099         {
1100             tcu::Surface referenceFrame(viewportWidth, viewportHeight);
1101             tcu::Surface errorMask(viewportWidth, viewportHeight);
1102 
1103             int numFailedPixels = 0;
1104 
1105             for (int gridY = 0; gridY < gridHeight; gridY++)
1106             {
1107                 for (int gridX = 0; gridX < gridWidth; gridX++)
1108                 {
1109                     const int curX    = cellWidth * gridX;
1110                     const int curY    = cellHeight * gridY;
1111                     const int curW    = gridX + 1 == gridWidth ? (viewportWidth - curX) : cellWidth;
1112                     const int curH    = gridY + 1 == gridHeight ? (viewportHeight - curY) : cellHeight;
1113                     const int cellNdx = gridY * gridWidth + gridX;
1114 
1115                     getReferenceParams(refParams, cellNdx);
1116 
1117                     refParams.imageViewMinLodMode = imageViewLodMode;
1118 
1119                     // Compute texcoord.
1120                     if (refParams.samplerType == glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT)
1121                         getBasicTexCoord2DImageViewMinLodIntTexCoord(texCoord);
1122                     else
1123                         getBasicTexCoord2D(texCoord, cellNdx);
1124 
1125                     // Render ideal result
1126                     sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH), refTexture,
1127                                   &texCoord[0], refParams);
1128 
1129                     // Compare this cell
1130                     numFailedPixels += computeTextureLookupDiff(
1131                         tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1132                         tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1133                         tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getTexture(),
1134                         &texCoord[0], refParams, lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
1135                 }
1136             }
1137 
1138             if (numFailedPixels > 0)
1139             {
1140                 m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1141                                                     << TestLog::Image("ErrorMask", "Error mask", errorMask);
1142             }
1143             return numFailedPixels;
1144         };
1145 
1146         m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
1147                                             << TestLog::Image("Rendered", "Rendered image", renderedFrame);
1148 
1149         int numFailedPixels = compareAndLogImages();
1150 
1151         if (numFailedPixels > 0 && refParams.imageViewMinLod > 0.0f)
1152         {
1153             numFailedPixels = compareAndLogImages(tcu::IMAGEVIEWMINLODMODE_ALTERNATIVE);
1154         }
1155         m_context.getTestContext().getLog() << TestLog::EndImageSet;
1156 
1157         if (numFailedPixels > 0)
1158             m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found "
1159                                                 << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
1160 
1161         {
1162             const bool isOk = numFailedPixels == 0;
1163             return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
1164         }
1165     }
1166 }
1167 
1168 class Texture2DMinLodTestInstance : public Texture2DLodControlTestInstance
1169 {
1170 public:
Texture2DMinLodTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1171     Texture2DMinLodTestInstance(Context &context, const Texture2DMipmapTestCaseParameters &testParameters)
1172         : Texture2DLodControlTestInstance(context, testParameters)
1173     {
1174     }
1175 
1176 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1177     void getReferenceParams(ReferenceParams &params, int cellNdx)
1178     {
1179         params.minLod = getMinLodForCell(cellNdx);
1180     }
1181 };
1182 
1183 class Texture2DMaxLodTestInstance : public Texture2DLodControlTestInstance
1184 {
1185 public:
Texture2DMaxLodTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1186     Texture2DMaxLodTestInstance(Context &context, const Texture2DMipmapTestCaseParameters &testParameters)
1187         : Texture2DLodControlTestInstance(context, testParameters)
1188     {
1189     }
1190 
1191 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1192     void getReferenceParams(ReferenceParams &params, int cellNdx)
1193     {
1194         params.maxLod = getMaxLodForCell(cellNdx);
1195     }
1196 };
1197 
1198 class Texture2DBaseLevelTestInstance : public Texture2DLodControlTestInstance
1199 {
1200 public:
Texture2DBaseLevelTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1201     Texture2DBaseLevelTestInstance(Context &context, const Texture2DMipmapTestCaseParameters &testParameters)
1202         : Texture2DLodControlTestInstance(context, testParameters)
1203         , m_testParam(testParameters)
1204     {
1205     }
1206 
1207 protected:
1208     const Texture2DMipmapTestCaseParameters m_testParam;
1209 
getBaseLevel(int cellNdx) const1210     int getBaseLevel(int cellNdx) const
1211     {
1212         const int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight)) + 1;
1213         const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0xac2f274a) % numLevels;
1214 
1215         return baseLevel;
1216     }
1217 
getReferenceParams(ReferenceParams & params,int cellNdx)1218     void getReferenceParams(ReferenceParams &params, int cellNdx)
1219     {
1220         params.baseLevel = getBaseLevel(cellNdx);
1221     }
1222 };
1223 
1224 class Texture2DMaxLevelTestInstance : public Texture2DLodControlTestInstance
1225 {
1226 public:
Texture2DMaxLevelTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1227     Texture2DMaxLevelTestInstance(Context &context, const Texture2DMipmapTestCaseParameters &testParameters)
1228         : Texture2DLodControlTestInstance(context, testParameters)
1229         , m_testParam(testParameters)
1230     {
1231     }
1232 
1233 protected:
1234     const Texture2DMipmapTestCaseParameters m_testParam;
1235 
getMaxLevel(int cellNdx) const1236     int getMaxLevel(int cellNdx) const
1237     {
1238         const int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight)) + 1;
1239         const int maxLevel  = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x82cfa4e) % numLevels;
1240 
1241         return maxLevel;
1242     }
1243 
getReferenceParams(ReferenceParams & params,int cellNdx)1244     void getReferenceParams(ReferenceParams &params, int cellNdx)
1245     {
1246         params.maxLevel = getMaxLevel(cellNdx);
1247     }
1248 };
1249 
1250 // TextureCubeLodControlTestInstance
1251 class TextureCubeLodControlTestInstance : public TestInstance
1252 {
1253 public:
1254     typedef TextureCubeMipmapTestCaseParameters ParameterType;
1255 
1256     TextureCubeLodControlTestInstance(Context &context, const ParameterType &testParameters);
1257     ~TextureCubeLodControlTestInstance(void);
1258 
1259     virtual tcu::TestStatus iterate(void);
1260 
1261 protected:
1262     virtual void getReferenceParams(ReferenceParams &params, int cellNdx) = DE_NULL;
1263 
1264     const int m_texSize;
1265 
1266 private:
1267     TextureCubeLodControlTestInstance(const TextureCubeLodControlTestInstance &other);
1268     TextureCubeLodControlTestInstance &operator=(const TextureCubeLodControlTestInstance &other);
1269 
1270     const ParameterType m_testParameters;
1271     tcu::Sampler::FilterMode m_minFilter;
1272     TestTextureCubeSp m_texture;
1273     TextureRenderer m_renderer;
1274 };
1275 
TextureCubeLodControlTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1276 TextureCubeLodControlTestInstance::TextureCubeLodControlTestInstance(
1277     Context &context, const TextureCubeMipmapTestCaseParameters &testParameters)
1278     : TestInstance(context)
1279     , m_texSize(64)
1280     , m_testParameters(testParameters)
1281     , m_minFilter(testParameters.minFilter)
1282     , m_texture(DE_NULL)
1283 
1284     , m_renderer(context, testParameters.sampleCount, m_texSize * 2, m_texSize * 2)
1285 {
1286     const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1287     const int numLevels   = deLog2Floor32(m_texSize) + 1;
1288 
1289     m_texture = TestTextureCubeSp(new pipeline::TestTextureCube(vk::mapVkFormat(format), m_texSize));
1290 
1291     // Fill texture with colored grid.
1292     for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
1293     {
1294         for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1295         {
1296             const uint32_t step = 0xff / (numLevels - 1);
1297             const uint32_t inc  = deClamp32(step * levelNdx, 0x00, 0xff);
1298             const uint32_t dec  = 0xff - inc;
1299             uint32_t rgb        = 0;
1300 
1301             switch (faceNdx)
1302             {
1303             case 0:
1304                 rgb = (inc << 16) | (dec << 8) | 255;
1305                 break;
1306             case 1:
1307                 rgb = (255 << 16) | (inc << 8) | dec;
1308                 break;
1309             case 2:
1310                 rgb = (dec << 16) | (255 << 8) | inc;
1311                 break;
1312             case 3:
1313                 rgb = (dec << 16) | (inc << 8) | 255;
1314                 break;
1315             case 4:
1316                 rgb = (255 << 16) | (dec << 8) | inc;
1317                 break;
1318             case 5:
1319                 rgb = (inc << 16) | (255 << 8) | dec;
1320                 break;
1321             }
1322 
1323             const uint32_t color = 0xff000000 | rgb;
1324 
1325             tcu::clear(m_texture->getLevel(levelNdx, (tcu::CubeFace)faceNdx), tcu::RGBA(color).toVec());
1326         }
1327     }
1328 
1329     m_renderer.addCubeTexture(m_texture, testParameters.aspectMask);
1330 }
1331 
~TextureCubeLodControlTestInstance(void)1332 TextureCubeLodControlTestInstance::~TextureCubeLodControlTestInstance(void)
1333 {
1334 }
1335 
iterate(void)1336 tcu::TestStatus TextureCubeLodControlTestInstance::iterate(void)
1337 {
1338     const tcu::Sampler::WrapMode wrapS       = Sampler::CLAMP_TO_EDGE;
1339     const tcu::Sampler::WrapMode wrapT       = Sampler::CLAMP_TO_EDGE;
1340     const tcu::Sampler::FilterMode magFilter = Sampler::NEAREST;
1341 
1342     const tcu::TextureCube &refTexture = m_texture->getTexture();
1343     const int viewportWidth            = m_renderer.getRenderWidth();
1344     const int viewportHeight           = m_renderer.getRenderHeight();
1345 
1346     tcu::Sampler sampler = util::createSampler(wrapS, wrapT, m_minFilter, magFilter);
1347     ReferenceParams refParams(TEXTURETYPE_CUBE, sampler);
1348     vector<float> texCoord;
1349     tcu::Surface renderedFrame(viewportWidth, viewportHeight);
1350 
1351     refParams.maxLevel = deLog2Floor32(m_texSize);
1352 
1353     // Compute grid.
1354     vector<tcu::IVec4> gridLayout;
1355     computeGridLayout(gridLayout, viewportWidth, viewportHeight);
1356 
1357     for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
1358     {
1359         const int curX               = gridLayout[cellNdx].x();
1360         const int curY               = gridLayout[cellNdx].y();
1361         const int curW               = gridLayout[cellNdx].z();
1362         const int curH               = gridLayout[cellNdx].w();
1363         const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
1364 
1365         computeQuadTexCoordCube(texCoord, cubeFace);
1366         getReferenceParams(refParams, cellNdx);
1367 
1368         // Render with GL.
1369         m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
1370         m_renderer.getTextureBinding(0)->updateTextureViewMipLevels(refParams.baseLevel, refParams.maxLevel,
1371                                                                     refParams.imageViewMinLod);
1372         m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
1373     }
1374 
1375     // Render reference and compare
1376     {
1377         const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1378         const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
1379         tcu::LookupPrecision lookupPrec;
1380         tcu::LodPrecision lodPrec;
1381 
1382         // Params for rendering reference
1383         refParams.sampler                 = util::createSampler(wrapS, wrapT, m_testParameters.minFilter, magFilter);
1384         refParams.sampler.seamlessCubeMap = true;
1385         refParams.lodMode                 = LODMODE_EXACT;
1386 
1387         // Comparison parameters
1388         lookupPrec.colorMask      = getCompareMask(pixelFormat);
1389         lookupPrec.colorThreshold = tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - 2, IVec4(0)));
1390         lookupPrec.coordBits      = tcu::IVec3(10);
1391         lookupPrec.uvwBits        = tcu::IVec3(5, 5, 0);
1392         lodPrec.derivateBits      = 10;
1393         lodPrec.lodBits           = 6;
1394 
1395         auto compareAndLogImages = [&](tcu::ImageViewMinLodMode imageViewLodMode = tcu::IMAGEVIEWMINLODMODE_PREFERRED)
1396         {
1397             tcu::Surface referenceFrame(viewportWidth, viewportHeight);
1398             tcu::Surface errorMask(viewportWidth, viewportHeight);
1399             int numFailedPixels = 0;
1400 
1401             for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
1402             {
1403                 const int curX               = gridLayout[cellNdx].x();
1404                 const int curY               = gridLayout[cellNdx].y();
1405                 const int curW               = gridLayout[cellNdx].z();
1406                 const int curH               = gridLayout[cellNdx].w();
1407                 const tcu::CubeFace cubeFace = (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
1408 
1409                 computeQuadTexCoordCube(texCoord, cubeFace);
1410                 getReferenceParams(refParams, cellNdx);
1411 
1412                 refParams.imageViewMinLodMode = imageViewLodMode;
1413 
1414                 // Render ideal reference.
1415                 {
1416                     tcu::SurfaceAccess idealDst(referenceFrame, pixelFormat, curX, curY, curW, curH);
1417                     sampleTexture(idealDst, refTexture, &texCoord[0], refParams);
1418                 }
1419 
1420                 // Compare this cell
1421                 numFailedPixels += computeTextureLookupDiff(
1422                     tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1423                     tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1424                     tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getTexture(),
1425                     &texCoord[0], refParams, lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
1426             }
1427             if (numFailedPixels > 0)
1428             {
1429                 m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1430                                                     << TestLog::Image("ErrorMask", "Error mask", errorMask);
1431             }
1432             return numFailedPixels;
1433         };
1434 
1435         m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
1436                                             << TestLog::Image("Rendered", "Rendered image", renderedFrame);
1437 
1438         int numFailedPixels = compareAndLogImages();
1439 
1440         if (numFailedPixels > 0 && refParams.imageViewMinLod > 0.0f)
1441         {
1442             numFailedPixels = compareAndLogImages(tcu::IMAGEVIEWMINLODMODE_ALTERNATIVE);
1443         }
1444         m_context.getTestContext().getLog() << TestLog::EndImageSet;
1445 
1446         if (numFailedPixels > 0)
1447             m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found "
1448                                                 << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
1449 
1450         {
1451             const bool isOk = numFailedPixels == 0;
1452             return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
1453         }
1454     }
1455 }
1456 
1457 class TextureCubeMinLodTestInstance : public TextureCubeLodControlTestInstance
1458 {
1459 public:
TextureCubeMinLodTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1460     TextureCubeMinLodTestInstance(Context &context, const TextureCubeMipmapTestCaseParameters &testParameters)
1461         : TextureCubeLodControlTestInstance(context, testParameters)
1462     {
1463     }
1464 
1465 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1466     void getReferenceParams(ReferenceParams &params, int cellNdx)
1467     {
1468         params.minLod = getMinLodForCell(cellNdx);
1469     }
1470 };
1471 
1472 class TextureCubeMaxLodTestInstance : public TextureCubeLodControlTestInstance
1473 {
1474 public:
TextureCubeMaxLodTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1475     TextureCubeMaxLodTestInstance(Context &context, const TextureCubeMipmapTestCaseParameters &testParameters)
1476         : TextureCubeLodControlTestInstance(context, testParameters)
1477     {
1478     }
1479 
1480 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1481     void getReferenceParams(ReferenceParams &params, int cellNdx)
1482     {
1483         params.maxLod = getMaxLodForCell(cellNdx);
1484     }
1485 };
1486 
1487 class TextureCubeBaseLevelTestInstance : public TextureCubeLodControlTestInstance
1488 {
1489 public:
TextureCubeBaseLevelTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1490     TextureCubeBaseLevelTestInstance(Context &context, const TextureCubeMipmapTestCaseParameters &testParameters)
1491         : TextureCubeLodControlTestInstance(context, testParameters)
1492         , m_testParam(testParameters)
1493     {
1494     }
1495 
1496 protected:
1497     const TextureCubeMipmapTestCaseParameters m_testParam;
1498 
getBaseLevel(int cellNdx) const1499     int getBaseLevel(int cellNdx) const
1500     {
1501         const int numLevels = deLog2Floor32(m_texSize) + 1;
1502         const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x23fae13) % numLevels;
1503 
1504         return baseLevel;
1505     }
1506 
getReferenceParams(ReferenceParams & params,int cellNdx)1507     void getReferenceParams(ReferenceParams &params, int cellNdx)
1508     {
1509         params.baseLevel = getBaseLevel(cellNdx);
1510     }
1511 };
1512 
1513 class TextureCubeMaxLevelTestInstance : public TextureCubeLodControlTestInstance
1514 {
1515 public:
TextureCubeMaxLevelTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1516     TextureCubeMaxLevelTestInstance(Context &context, const TextureCubeMipmapTestCaseParameters &testParameters)
1517         : TextureCubeLodControlTestInstance(context, testParameters)
1518         , m_testParam(testParameters)
1519     {
1520     }
1521 
1522 protected:
1523     const TextureCubeMipmapTestCaseParameters m_testParam;
getMaxLevel(int cellNdx) const1524     int getMaxLevel(int cellNdx) const
1525     {
1526         const int numLevels = deLog2Floor32(m_texSize) + 1;
1527         const int maxLevel  = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x974e21) % numLevels;
1528 
1529         return maxLevel;
1530     }
1531 
getReferenceParams(ReferenceParams & params,int cellNdx)1532     void getReferenceParams(ReferenceParams &params, int cellNdx)
1533     {
1534         params.maxLevel = getMaxLevel(cellNdx);
1535     }
1536 };
1537 
1538 // Texture3DLodControlTestInstance
1539 class Texture3DLodControlTestInstance : public TestInstance
1540 {
1541 public:
1542     typedef Texture3DMipmapTestCaseParameters ParameterType;
1543 
1544     Texture3DLodControlTestInstance(Context &context, const ParameterType &testParameters);
1545     ~Texture3DLodControlTestInstance(void);
1546 
1547     virtual tcu::TestStatus iterate(void);
1548 
1549 protected:
1550     virtual void getReferenceParams(ReferenceParams &params, int cellNdx) = DE_NULL;
1551 
1552     const int m_texWidth;
1553     const int m_texHeight;
1554     const int m_texDepth;
1555 
1556 private:
1557     Texture3DLodControlTestInstance(const Texture3DLodControlTestInstance &other);
1558     Texture3DLodControlTestInstance &operator=(const Texture3DLodControlTestInstance &other);
1559 
1560     const ParameterType m_testParameters;
1561     tcu::Sampler::FilterMode m_minFilter;
1562     TestTexture3DSp m_texture;
1563     TextureRenderer m_renderer;
1564 };
1565 
Texture3DLodControlTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1566 Texture3DLodControlTestInstance::Texture3DLodControlTestInstance(
1567     Context &context, const Texture3DMipmapTestCaseParameters &testParameters)
1568     : TestInstance(context)
1569     , m_texWidth(32)
1570     , m_texHeight(32)
1571     , m_texDepth(32)
1572     , m_testParameters(testParameters)
1573     , m_minFilter(testParameters.minFilter)
1574     , m_texture(DE_NULL)
1575     , m_renderer(context, testParameters.sampleCount, m_texWidth * 4, m_texHeight * 4, vk::makeComponentMappingRGBA(),
1576                  testParameters.testType > util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD,
1577                  testParameters.testType >= util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD)
1578 {
1579     const VkFormat format          = VK_FORMAT_R8G8B8A8_UNORM;
1580     tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(mapVkFormat(format));
1581     const tcu::Vec4 &cScale        = fmtInfo.lookupScale;
1582     const tcu::Vec4 &cBias         = fmtInfo.lookupBias;
1583     const int numLevels            = deLog2Floor32(de::max(de::max(m_texWidth, m_texHeight), m_texDepth)) + 1;
1584 
1585     m_texture =
1586         TestTexture3DSp(new pipeline::TestTexture3D(vk::mapVkFormat(format), m_texWidth, m_texHeight, m_texDepth));
1587 
1588     // Fill texture with colored grid.
1589     for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1590     {
1591         const uint32_t step  = 0xff / (numLevels - 1);
1592         const uint32_t inc   = deClamp32(step * levelNdx, 0x00, 0xff);
1593         const uint32_t dec   = 0xff - inc;
1594         const uint32_t rgb   = (inc << 16) | (dec << 8) | 0xff;
1595         const uint32_t color = 0xff000000 | rgb;
1596 
1597         tcu::clear(m_texture->getLevel(levelNdx, 0), tcu::RGBA(color).toVec() * cScale + cBias);
1598     }
1599 
1600     m_renderer.add3DTexture(m_texture, testParameters.aspectMask);
1601 }
1602 
~Texture3DLodControlTestInstance(void)1603 Texture3DLodControlTestInstance::~Texture3DLodControlTestInstance(void)
1604 {
1605 }
1606 
iterate(void)1607 tcu::TestStatus Texture3DLodControlTestInstance::iterate(void)
1608 {
1609     const tcu::Sampler::WrapMode wrapS       = Sampler::CLAMP_TO_EDGE;
1610     const tcu::Sampler::WrapMode wrapT       = Sampler::CLAMP_TO_EDGE;
1611     const tcu::Sampler::WrapMode wrapR       = Sampler::CLAMP_TO_EDGE;
1612     const tcu::Sampler::FilterMode magFilter = Sampler::NEAREST;
1613 
1614     const tcu::Texture3D &refTexture     = m_texture->getTexture();
1615     const tcu::TextureFormat &texFmt     = refTexture.getFormat();
1616     const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt);
1617     const int viewportWidth              = m_renderer.getRenderWidth();
1618     const int viewportHeight             = m_renderer.getRenderHeight();
1619 
1620     tcu::Sampler sampler = util::createSampler(wrapS, wrapT, m_minFilter, magFilter);
1621     ReferenceParams refParams(TEXTURETYPE_3D, sampler);
1622     vector<float> texCoord;
1623     tcu::Surface renderedFrame(viewportWidth, viewportHeight);
1624 
1625     // Viewport is divided into 4x4 grid.
1626     const int gridWidth  = 4;
1627     const int gridHeight = 4;
1628     const int cellWidth  = viewportWidth / gridWidth;
1629     const int cellHeight = viewportHeight / gridHeight;
1630 
1631     // Sampling parameters.
1632     refParams.sampler     = util::createSampler(wrapS, wrapT, wrapR, m_testParameters.minFilter, magFilter);
1633     refParams.samplerType = getSamplerType(texFmt);
1634     refParams.colorBias   = fmtInfo.lookupBias;
1635     refParams.colorScale  = fmtInfo.lookupScale;
1636     refParams.maxLevel    = deLog2Floor32(de::max(de::max(m_texWidth, m_texHeight), m_texDepth));
1637 
1638     // Render cells.
1639     for (int gridY = 0; gridY < gridHeight; gridY++)
1640     {
1641         for (int gridX = 0; gridX < gridWidth; gridX++)
1642         {
1643             const int curX    = cellWidth * gridX;
1644             const int curY    = cellHeight * gridY;
1645             const int curW    = gridX + 1 == gridWidth ? (viewportWidth - curX) : cellWidth;
1646             const int curH    = gridY + 1 == gridHeight ? (viewportHeight - curY) : cellHeight;
1647             const int cellNdx = gridY * gridWidth + gridX;
1648 
1649             // Compute texcoord.
1650             getBasicTexCoord3D(texCoord, cellNdx);
1651 
1652             getReferenceParams(refParams, cellNdx);
1653             //Render
1654             m_renderer.setViewport((float)curX, (float)curY, (float)curW, (float)curH);
1655             m_renderer.getTextureBinding(0)->updateTextureViewMipLevels(refParams.baseLevel, refParams.maxLevel,
1656                                                                         refParams.imageViewMinLod);
1657             m_renderer.renderQuad(renderedFrame, 0, &texCoord[0], refParams);
1658         }
1659     }
1660 
1661     // Compare and log
1662     {
1663         const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1664         const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
1665         const bool isTrilinear =
1666             m_minFilter == Sampler::NEAREST_MIPMAP_LINEAR || m_minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
1667         tcu::LookupPrecision lookupPrec;
1668         tcu::LodPrecision lodPrec;
1669 
1670         lookupPrec.coordBits = tcu::IVec3(20, 20, 20);
1671         lookupPrec.uvwBits   = tcu::IVec3(16, 16, 16); // Doesn't really matter since pixels are unicolored.
1672         lookupPrec.colorThreshold =
1673             tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
1674         lookupPrec.colorMask = getCompareMask(pixelFormat);
1675         lodPrec.derivateBits = 10;
1676         lodPrec.lodBits      = 8;
1677 
1678         auto compareAndLogImages = [&](tcu::ImageViewMinLodMode imageViewLodMode = tcu::IMAGEVIEWMINLODMODE_PREFERRED)
1679         {
1680             tcu::Surface referenceFrame(viewportWidth, viewportHeight);
1681             tcu::Surface errorMask(viewportWidth, viewportHeight);
1682             int numFailedPixels = 0;
1683 
1684             for (int gridY = 0; gridY < gridHeight; gridY++)
1685             {
1686                 for (int gridX = 0; gridX < gridWidth; gridX++)
1687                 {
1688                     const int curX    = cellWidth * gridX;
1689                     const int curY    = cellHeight * gridY;
1690                     const int curW    = gridX + 1 == gridWidth ? (viewportWidth - curX) : cellWidth;
1691                     const int curH    = gridY + 1 == gridHeight ? (viewportHeight - curY) : cellHeight;
1692                     const int cellNdx = gridY * gridWidth + gridX;
1693 
1694                     getReferenceParams(refParams, cellNdx);
1695 
1696                     refParams.imageViewMinLodMode = imageViewLodMode;
1697 
1698                     // Compute texcoord.
1699                     if (refParams.samplerType == glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT)
1700                         getBasicTexCoord3DImageViewMinlodIntTexCoord(texCoord);
1701                     else
1702                         getBasicTexCoord3D(texCoord, cellNdx);
1703 
1704                     // Render ideal result
1705                     sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH), refTexture,
1706                                   &texCoord[0], refParams);
1707 
1708                     // Compare this cell
1709                     numFailedPixels += computeTextureLookupDiff(
1710                         tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
1711                         tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
1712                         tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH), m_texture->getTexture(),
1713                         &texCoord[0], refParams, lookupPrec, lodPrec, m_context.getTestContext().getWatchDog());
1714                 }
1715             }
1716             if (numFailedPixels > 0)
1717             {
1718                 m_context.getTestContext().getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
1719                                                     << TestLog::Image("ErrorMask", "Error mask", errorMask);
1720             }
1721 
1722             return numFailedPixels;
1723         };
1724 
1725         m_context.getTestContext().getLog() << TestLog::ImageSet("Result", "Verification result")
1726                                             << TestLog::Image("Rendered", "Rendered image", renderedFrame);
1727 
1728         int numFailedPixels = compareAndLogImages();
1729 
1730         if (numFailedPixels > 0 && refParams.imageViewMinLod > 0.0f)
1731         {
1732             numFailedPixels = compareAndLogImages(tcu::IMAGEVIEWMINLODMODE_ALTERNATIVE);
1733         }
1734         m_context.getTestContext().getLog() << TestLog::EndImageSet;
1735 
1736         if (numFailedPixels > 0)
1737             m_context.getTestContext().getLog() << TestLog::Message << "ERROR: Image verification failed, found "
1738                                                 << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
1739 
1740         {
1741             const bool isOk = numFailedPixels == 0;
1742             return isOk ? tcu::TestStatus::pass("pass") : tcu::TestStatus::fail("fail");
1743         }
1744     }
1745 }
1746 
1747 class Texture3DMinLodTestInstance : public Texture3DLodControlTestInstance
1748 {
1749 public:
Texture3DMinLodTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1750     Texture3DMinLodTestInstance(Context &context, const Texture3DMipmapTestCaseParameters &testParameters)
1751         : Texture3DLodControlTestInstance(context, testParameters)
1752     {
1753     }
1754 
1755 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1756     void getReferenceParams(ReferenceParams &params, int cellNdx)
1757     {
1758         params.minLod = getMinLodForCell(cellNdx);
1759     }
1760 };
1761 
1762 class Texture3DMaxLodTestInstance : public Texture3DLodControlTestInstance
1763 {
1764 public:
Texture3DMaxLodTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1765     Texture3DMaxLodTestInstance(Context &context, const Texture3DMipmapTestCaseParameters &testParameters)
1766         : Texture3DLodControlTestInstance(context, testParameters)
1767     {
1768     }
1769 
1770 protected:
getReferenceParams(ReferenceParams & params,int cellNdx)1771     void getReferenceParams(ReferenceParams &params, int cellNdx)
1772     {
1773         params.maxLod = getMaxLodForCell(cellNdx);
1774     }
1775 };
1776 
1777 class Texture3DBaseLevelTestInstance : public Texture3DLodControlTestInstance
1778 {
1779 public:
Texture3DBaseLevelTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1780     Texture3DBaseLevelTestInstance(Context &context, const Texture3DMipmapTestCaseParameters &testParameters)
1781         : Texture3DLodControlTestInstance(context, testParameters)
1782         , m_testParam(testParameters)
1783     {
1784     }
1785 
1786 protected:
1787     const Texture3DMipmapTestCaseParameters m_testParam;
1788 
getBaseLevel(int cellNdx) const1789     int getBaseLevel(int cellNdx) const
1790     {
1791         const int numLevels = deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth))) + 1;
1792         const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x7347e9) % numLevels;
1793 
1794         return baseLevel;
1795     }
1796 
getReferenceParams(ReferenceParams & params,int cellNdx)1797     void getReferenceParams(ReferenceParams &params, int cellNdx)
1798     {
1799         params.baseLevel = getBaseLevel(cellNdx);
1800     }
1801 };
1802 
1803 class Texture3DMaxLevelTestInstance : public Texture3DLodControlTestInstance
1804 {
1805 public:
Texture3DMaxLevelTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1806     Texture3DMaxLevelTestInstance(Context &context, const Texture3DMipmapTestCaseParameters &testParameters)
1807         : Texture3DLodControlTestInstance(context, testParameters)
1808         , m_testParam(testParameters)
1809     {
1810     }
1811 
1812 protected:
1813     const Texture3DMipmapTestCaseParameters m_testParam;
1814 
getMaxLevel(int cellNdx) const1815     int getMaxLevel(int cellNdx) const
1816     {
1817         const int numLevels = deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth))) + 1;
1818         const int maxLevel  = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x9111e7) % numLevels;
1819 
1820         return maxLevel;
1821     }
1822 
getReferenceParams(ReferenceParams & params,int cellNdx)1823     void getReferenceParams(ReferenceParams &params, int cellNdx)
1824     {
1825         params.maxLevel = getMaxLevel(cellNdx);
1826     }
1827 };
1828 
1829 #ifndef CTS_USES_VULKANSC
1830 
1831 class Texture2DImageViewMinLodTestInstance : public Texture2DLodControlTestInstance
1832 {
1833 public:
Texture2DImageViewMinLodTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1834     Texture2DImageViewMinLodTestInstance(Context &context, const Texture2DMipmapTestCaseParameters &testParameters)
1835         : Texture2DLodControlTestInstance(context, testParameters)
1836     {
1837     }
1838 
1839 protected:
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1840     float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
1841     {
1842         de::Random rnd(cellNdx + 1);
1843 
1844         // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1845         float minBaseLevel = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1846         return rnd.getFloat(minBaseLevel, (float)maxLevel);
1847     }
1848 
getReferenceParams(ReferenceParams & params,int cellNdx)1849     void getReferenceParams(ReferenceParams &params, int cellNdx)
1850     {
1851         params.minLod          = getMinLodForCell(cellNdx);
1852         params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
1853     }
1854 };
1855 
1856 class Texture2DImageViewMinLodBaseLevelTestInstance : public Texture2DLodControlTestInstance
1857 {
1858 public:
Texture2DImageViewMinLodBaseLevelTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)1859     Texture2DImageViewMinLodBaseLevelTestInstance(Context &context,
1860                                                   const Texture2DMipmapTestCaseParameters &testParameters)
1861         : Texture2DLodControlTestInstance(context, testParameters)
1862         , m_testParam(testParameters)
1863     {
1864     }
1865 
1866 protected:
1867     const Texture2DMipmapTestCaseParameters m_testParam;
1868 
getBaseLevel(int cellNdx) const1869     int getBaseLevel(int cellNdx) const
1870     {
1871         const int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight)) + 1;
1872         const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0xac2f274a) % numLevels;
1873 
1874         return baseLevel;
1875     }
1876 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1877     float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
1878     {
1879         de::Random rnd(cellNdx + 1);
1880 
1881         // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1882         float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1883         return rnd.getFloat(minValue, (float)maxLevel);
1884     }
1885 
getReferenceParams(ReferenceParams & params,int cellNdx)1886     void getReferenceParams(ReferenceParams &params, int cellNdx)
1887     {
1888         params.baseLevel       = getBaseLevel(cellNdx);
1889         params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
1890     }
1891 };
1892 
1893 class Texture3DImageViewMinLodTestInstance : public Texture3DLodControlTestInstance
1894 {
1895 public:
Texture3DImageViewMinLodTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1896     Texture3DImageViewMinLodTestInstance(Context &context, const Texture3DMipmapTestCaseParameters &testParameters)
1897         : Texture3DLodControlTestInstance(context, testParameters)
1898     {
1899     }
1900 
1901 protected:
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1902     float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
1903     {
1904         de::Random rnd(cellNdx + 1);
1905 
1906         // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1907         float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1908         return rnd.getFloat(minValue, (float)maxLevel);
1909     }
1910 
getReferenceParams(ReferenceParams & params,int cellNdx)1911     void getReferenceParams(ReferenceParams &params, int cellNdx)
1912     {
1913         params.minLod          = getMinLodForCell(cellNdx);
1914         params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
1915     }
1916 };
1917 
1918 class Texture3DImageViewMinLodBaseLevelTestInstance : public Texture3DLodControlTestInstance
1919 {
1920 public:
Texture3DImageViewMinLodBaseLevelTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)1921     Texture3DImageViewMinLodBaseLevelTestInstance(Context &context,
1922                                                   const Texture3DMipmapTestCaseParameters &testParameters)
1923         : Texture3DLodControlTestInstance(context, testParameters)
1924         , m_testParam(testParameters)
1925     {
1926     }
1927 
1928 protected:
1929     const Texture3DMipmapTestCaseParameters m_testParam;
1930 
getBaseLevel(int cellNdx) const1931     int getBaseLevel(int cellNdx) const
1932     {
1933         const int numLevels = deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth))) + 1;
1934         const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x7347e9) % numLevels;
1935 
1936         return baseLevel;
1937     }
1938 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1939     float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
1940     {
1941         de::Random rnd(cellNdx + 1);
1942 
1943         // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1944         float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1945         return rnd.getFloat(minValue, (float)maxLevel);
1946     }
1947 
getReferenceParams(ReferenceParams & params,int cellNdx)1948     void getReferenceParams(ReferenceParams &params, int cellNdx)
1949     {
1950         params.baseLevel       = getBaseLevel(cellNdx);
1951         params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
1952     }
1953 };
1954 
1955 class TextureCubeImageViewMinLodTestInstance : public TextureCubeLodControlTestInstance
1956 {
1957 public:
TextureCubeImageViewMinLodTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1958     TextureCubeImageViewMinLodTestInstance(Context &context, const TextureCubeMipmapTestCaseParameters &testParameters)
1959         : TextureCubeLodControlTestInstance(context, testParameters)
1960     {
1961     }
1962 
1963 protected:
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const1964     float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
1965     {
1966         de::Random rnd(cellNdx + 1);
1967 
1968         // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
1969         float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
1970         return rnd.getFloat(minValue, (float)maxLevel);
1971     }
1972 
getReferenceParams(ReferenceParams & params,int cellNdx)1973     void getReferenceParams(ReferenceParams &params, int cellNdx)
1974     {
1975         params.minLod          = getMinLodForCell(cellNdx);
1976         params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
1977     }
1978 };
1979 
1980 class TextureCubeImageViewMinLodBaseLevelTestInstance : public TextureCubeLodControlTestInstance
1981 {
1982 public:
TextureCubeImageViewMinLodBaseLevelTestInstance(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)1983     TextureCubeImageViewMinLodBaseLevelTestInstance(Context &context,
1984                                                     const TextureCubeMipmapTestCaseParameters &testParameters)
1985         : TextureCubeLodControlTestInstance(context, testParameters)
1986         , m_testParam(testParameters)
1987     {
1988     }
1989 
1990 protected:
1991     const TextureCubeMipmapTestCaseParameters m_testParam;
1992 
getBaseLevel(int cellNdx) const1993     int getBaseLevel(int cellNdx) const
1994     {
1995         const int numLevels = deLog2Floor32(m_texSize) + 1;
1996         const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x23fae13) % numLevels;
1997 
1998         return baseLevel;
1999     }
2000 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const2001     float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
2002     {
2003         de::Random rnd(cellNdx + 1);
2004 
2005         // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
2006         float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
2007         return rnd.getFloat(minValue, (float)maxLevel);
2008     }
2009 
getReferenceParams(ReferenceParams & params,int cellNdx)2010     void getReferenceParams(ReferenceParams &params, int cellNdx)
2011     {
2012         params.baseLevel       = getBaseLevel(cellNdx);
2013         params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
2014     }
2015 };
2016 
2017 class Texture2DImageViewMinLodIntTexCoordTestInstance : public Texture2DLodControlTestInstance
2018 {
2019 public:
Texture2DImageViewMinLodIntTexCoordTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)2020     Texture2DImageViewMinLodIntTexCoordTestInstance(Context &context,
2021                                                     const Texture2DMipmapTestCaseParameters &testParameters)
2022         : Texture2DLodControlTestInstance(context, testParameters)
2023         , m_testParam(testParameters)
2024     {
2025     }
2026 
2027 protected:
2028     const Texture2DMipmapTestCaseParameters m_testParam;
2029 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const2030     float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
2031     {
2032         de::Random rnd(cellNdx + 1);
2033 
2034         // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
2035         float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
2036         return rnd.getFloat(minValue, (float)maxLevel);
2037     }
2038 
getLodTexelFetch(int cellNdx,int baseLevel,int maxLevel) const2039     int getLodTexelFetch(int cellNdx, int baseLevel, int maxLevel) const
2040     {
2041         de::Random rnd(cellNdx + 1);
2042         return rnd.getInt(baseLevel, maxLevel) - baseLevel;
2043     }
2044 
getReferenceParams(ReferenceParams & params,int cellNdx)2045     void getReferenceParams(ReferenceParams &params, int cellNdx)
2046     {
2047         params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
2048         params.samplerType     = glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT;
2049         params.lodTexelFetch   = getLodTexelFetch(cellNdx, params.baseLevel, params.maxLevel);
2050     }
2051 };
2052 
2053 class Texture2DImageViewMinLodBaseLevelIntTexCoordTestInstance : public Texture2DLodControlTestInstance
2054 {
2055 public:
Texture2DImageViewMinLodBaseLevelIntTexCoordTestInstance(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)2056     Texture2DImageViewMinLodBaseLevelIntTexCoordTestInstance(Context &context,
2057                                                              const Texture2DMipmapTestCaseParameters &testParameters)
2058         : Texture2DLodControlTestInstance(context, testParameters)
2059         , m_testParam(testParameters)
2060     {
2061     }
2062 
2063 protected:
2064     const Texture2DMipmapTestCaseParameters m_testParam;
2065 
getBaseLevel(int cellNdx) const2066     int getBaseLevel(int cellNdx) const
2067     {
2068         const int numLevels = deLog2Floor32(de::max(m_texWidth, m_texHeight)) + 1;
2069         const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0xac2f274a) % numLevels;
2070 
2071         return baseLevel;
2072     }
2073 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const2074     float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
2075     {
2076         de::Random rnd(cellNdx + 1);
2077 
2078         // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
2079         float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
2080         return rnd.getFloat(minValue, (float)maxLevel);
2081     }
2082 
getLodTexelFetch(int cellNdx,int baseLevel,int maxLevel) const2083     int getLodTexelFetch(int cellNdx, int baseLevel, int maxLevel) const
2084     {
2085         de::Random rnd(cellNdx + 1);
2086         return rnd.getInt(baseLevel, maxLevel) - baseLevel;
2087     }
2088 
getReferenceParams(ReferenceParams & params,int cellNdx)2089     void getReferenceParams(ReferenceParams &params, int cellNdx)
2090     {
2091         params.baseLevel       = getBaseLevel(cellNdx);
2092         params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
2093         params.samplerType     = glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT;
2094         params.lodTexelFetch   = getLodTexelFetch(cellNdx, params.baseLevel, params.maxLevel);
2095     }
2096 };
2097 
2098 class Texture2DImageViewMinLodIntTexCoordTest : public vkt::TestCase
2099 {
2100 public:
2101     Texture2DImageViewMinLodIntTexCoordTest(tcu::TestContext &testContext, const string &name,
2102                                             const Texture2DMipmapTestCaseParameters &params);
2103     ~Texture2DImageViewMinLodIntTexCoordTest(void);
2104     void initPrograms(SourceCollections &sourceCollections) const;
2105     TestInstance *createInstance(Context &context) const;
2106     void checkSupport(Context &context) const;
2107 
2108 protected:
2109     const Texture2DMipmapTestCaseParameters m_params;
2110 };
2111 
Texture2DImageViewMinLodIntTexCoordTest(tcu::TestContext & testContext,const string & name,const Texture2DMipmapTestCaseParameters & params)2112 Texture2DImageViewMinLodIntTexCoordTest::Texture2DImageViewMinLodIntTexCoordTest(
2113     tcu::TestContext &testContext, const string &name, const Texture2DMipmapTestCaseParameters &params)
2114     : vkt::TestCase(testContext, name)
2115     , m_params(params)
2116 {
2117 }
2118 
~Texture2DImageViewMinLodIntTexCoordTest(void)2119 Texture2DImageViewMinLodIntTexCoordTest::~Texture2DImageViewMinLodIntTexCoordTest(void)
2120 {
2121 }
2122 
initPrograms(SourceCollections & sourceCollections) const2123 void Texture2DImageViewMinLodIntTexCoordTest::initPrograms(SourceCollections &sourceCollections) const
2124 {
2125     static const char *vertShader = "#version 450\n"
2126                                     "layout(location = 0) in vec4 a_position;\n"
2127                                     "layout(location = 1) in vec2 a_texCoord;\n"
2128                                     "out gl_PerVertex { vec4 gl_Position; };\n"
2129                                     "\n"
2130                                     "void main (void)\n"
2131                                     "{\n"
2132                                     "    gl_Position = a_position;\n"
2133                                     "}\n";
2134 
2135     static const char *fragShader =
2136         "#version 450\n"
2137         "layout(location = 0) out vec4 outColor;\n"
2138         "layout (set=0, binding=0, std140) uniform Block \n"
2139         "{\n"
2140         "  float u_bias;\n"
2141         "  float u_ref;\n"
2142         "  vec4 u_colorScale;\n"
2143         "  vec4 u_colorBias;\n"
2144         "  int u_lod;\n"
2145         "};\n\n"
2146         "layout (set=1, binding=0) uniform sampler2D u_sampler;\n"
2147         "void main (void)\n"
2148         "{\n"
2149         "  ivec2 texCoord = ivec2(0,0);\n" // Sampling always from the same coord, we are only interested on the lod.
2150         "  outColor = texelFetch(u_sampler, texCoord, u_lod) * u_colorScale + u_colorBias;\n"
2151         "}\n";
2152     sourceCollections.glslSources.add("vertex_2D_FETCH_LOD") << glu::VertexSource(vertShader);
2153     sourceCollections.glslSources.add("fragment_2D_FETCH_LOD") << glu::FragmentSource(fragShader);
2154 }
2155 
checkSupport(Context & context) const2156 void Texture2DImageViewMinLodIntTexCoordTest::checkSupport(Context &context) const
2157 {
2158     DE_ASSERT(m_params.testType > util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD);
2159 
2160     context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2161     context.requireDeviceFunctionality("VK_EXT_robustness2");
2162     vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
2163     imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
2164     imageViewMinLodFeatures.pNext = DE_NULL;
2165 
2166     VkPhysicalDeviceRobustness2FeaturesEXT robustness2Features;
2167     robustness2Features.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
2168     robustness2Features.pNext = &imageViewMinLodFeatures;
2169     vk::VkPhysicalDeviceFeatures2 features2;
2170 
2171     features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
2172     features2.pNext = &robustness2Features;
2173 
2174     context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2175 
2176     if (imageViewMinLodFeatures.minLod == false)
2177         TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
2178 
2179     if (robustness2Features.robustImageAccess2 == false)
2180         TCU_THROW(NotSupportedError, "VK_EXT_robustness2 robustImageAccess2 feature not supported");
2181 }
2182 
createInstance(Context & context) const2183 TestInstance *Texture2DImageViewMinLodIntTexCoordTest::createInstance(Context &context) const
2184 {
2185     if (m_params.testType == util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD)
2186         return new Texture2DImageViewMinLodIntTexCoordTestInstance(context, m_params);
2187     else
2188         return new Texture2DImageViewMinLodBaseLevelIntTexCoordTestInstance(context, m_params);
2189 }
2190 
2191 class Texture3DImageViewMinLodIntTexCoordTestInstance : public Texture3DLodControlTestInstance
2192 {
2193 public:
Texture3DImageViewMinLodIntTexCoordTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)2194     Texture3DImageViewMinLodIntTexCoordTestInstance(Context &context,
2195                                                     const Texture3DMipmapTestCaseParameters &testParameters)
2196         : Texture3DLodControlTestInstance(context, testParameters)
2197         , m_testParam(testParameters)
2198     {
2199     }
2200 
2201 protected:
2202     const Texture3DMipmapTestCaseParameters m_testParam;
2203 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const2204     float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
2205     {
2206         de::Random rnd(cellNdx + 1);
2207 
2208         // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
2209         float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
2210         return rnd.getFloat(minValue, (float)maxLevel);
2211     }
2212 
getLodTexelFetch(int cellNdx,int baseLevel,int maxLevel) const2213     int getLodTexelFetch(int cellNdx, int baseLevel, int maxLevel) const
2214     {
2215         de::Random rnd(cellNdx + 1);
2216         return rnd.getInt(baseLevel, maxLevel) - baseLevel;
2217     }
2218 
getReferenceParams(ReferenceParams & params,int cellNdx)2219     void getReferenceParams(ReferenceParams &params, int cellNdx)
2220     {
2221         params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
2222         params.samplerType     = glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT;
2223         params.lodTexelFetch   = getLodTexelFetch(cellNdx, params.baseLevel, params.maxLevel);
2224     }
2225 };
2226 
2227 class Texture3DImageViewMinLodBaseLevelIntTexCoordTestInstance : public Texture3DLodControlTestInstance
2228 {
2229 public:
Texture3DImageViewMinLodBaseLevelIntTexCoordTestInstance(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)2230     Texture3DImageViewMinLodBaseLevelIntTexCoordTestInstance(Context &context,
2231                                                              const Texture3DMipmapTestCaseParameters &testParameters)
2232         : Texture3DLodControlTestInstance(context, testParameters)
2233         , m_testParam(testParameters)
2234     {
2235     }
2236 
2237 protected:
2238     const Texture3DMipmapTestCaseParameters m_testParam;
2239 
getBaseLevel(int cellNdx) const2240     int getBaseLevel(int cellNdx) const
2241     {
2242         const int numLevels = deLog2Floor32(de::max(m_texWidth, de::max(m_texHeight, m_texDepth))) + 1;
2243         const int baseLevel = (deInt32Hash(cellNdx) ^ deStringHash(m_testParam.minFilterName) ^ 0x7347e9) % numLevels;
2244 
2245         return baseLevel;
2246     }
2247 
getImageViewMinLod(int cellNdx,int baseLevel,int maxLevel) const2248     float getImageViewMinLod(int cellNdx, int baseLevel, int maxLevel) const
2249     {
2250         de::Random rnd(cellNdx + 1);
2251 
2252         // baselevel + 1.0 as minimum, to test that minLod is working. If we go over the maximum, use that instead.
2253         float minValue = de::min((float)baseLevel + 1.0f, (float)maxLevel);
2254         return rnd.getFloat(minValue, (float)maxLevel);
2255     }
2256 
getLodTexelFetch(int cellNdx,int baseLevel,int maxLevel) const2257     int getLodTexelFetch(int cellNdx, int baseLevel, int maxLevel) const
2258     {
2259         de::Random rnd(cellNdx + 1);
2260         return rnd.getInt(baseLevel, maxLevel) - baseLevel;
2261     }
2262 
getReferenceParams(ReferenceParams & params,int cellNdx)2263     void getReferenceParams(ReferenceParams &params, int cellNdx)
2264     {
2265         params.baseLevel       = getBaseLevel(cellNdx);
2266         params.imageViewMinLod = getImageViewMinLod(cellNdx, params.baseLevel, params.maxLevel);
2267         params.samplerType     = glu::TextureTestUtil::SAMPLERTYPE_FETCH_FLOAT;
2268         params.lodTexelFetch   = getLodTexelFetch(cellNdx, params.baseLevel, params.maxLevel);
2269     }
2270 };
2271 
2272 class Texture3DImageViewMinLodIntTexCoordTest : public vkt::TestCase
2273 {
2274 public:
2275     Texture3DImageViewMinLodIntTexCoordTest(tcu::TestContext &testContext, const string &name,
2276                                             const Texture3DMipmapTestCaseParameters &params);
2277     ~Texture3DImageViewMinLodIntTexCoordTest(void);
2278     void initPrograms(SourceCollections &sourceCollections) const;
2279     TestInstance *createInstance(Context &context) const;
2280     void checkSupport(Context &context) const;
2281 
2282 protected:
2283     const Texture3DMipmapTestCaseParameters m_params;
2284 };
2285 
Texture3DImageViewMinLodIntTexCoordTest(tcu::TestContext & testContext,const string & name,const Texture3DMipmapTestCaseParameters & params)2286 Texture3DImageViewMinLodIntTexCoordTest::Texture3DImageViewMinLodIntTexCoordTest(
2287     tcu::TestContext &testContext, const string &name, const Texture3DMipmapTestCaseParameters &params)
2288     : vkt::TestCase(testContext, name)
2289     , m_params(params)
2290 {
2291 }
2292 
~Texture3DImageViewMinLodIntTexCoordTest(void)2293 Texture3DImageViewMinLodIntTexCoordTest::~Texture3DImageViewMinLodIntTexCoordTest(void)
2294 {
2295 }
2296 
initPrograms(SourceCollections & sourceCollections) const2297 void Texture3DImageViewMinLodIntTexCoordTest::initPrograms(SourceCollections &sourceCollections) const
2298 {
2299     static const char *vertShader = "#version 450\n"
2300                                     "layout(location = 0) in vec4 a_position;\n"
2301                                     "layout(location = 1) in vec3 a_texCoord;\n"
2302                                     "out gl_PerVertex { vec4 gl_Position; };\n"
2303                                     "\n"
2304                                     "void main (void)\n"
2305                                     "{\n"
2306                                     "    gl_Position = a_position;\n"
2307                                     "}\n";
2308 
2309     static const char *fragShader =
2310         "#version 450\n"
2311         "layout(location = 0) out vec4 outColor;\n"
2312         "layout (set=0, binding=0, std140) uniform Block \n"
2313         "{\n"
2314         "  float u_bias;\n"
2315         "  float u_ref;\n"
2316         "  vec4 u_colorScale;\n"
2317         "  vec4 u_colorBias;\n"
2318         "  int u_lod;\n"
2319         "};\n\n"
2320         "layout (set=1, binding=0) uniform sampler3D u_sampler;\n"
2321         "void main (void)\n"
2322         "{\n"
2323         "  ivec3 texCoord = ivec3(0,0,0);\n" // Sampling always from the same coord, we are only interested on the lod.
2324         "  outColor = texelFetch(u_sampler, texCoord, u_lod) * u_colorScale + u_colorBias;\n"
2325         "}\n";
2326     sourceCollections.glslSources.add("vertex_3D_FETCH_LOD") << glu::VertexSource(vertShader);
2327     sourceCollections.glslSources.add("fragment_3D_FETCH_LOD") << glu::FragmentSource(fragShader);
2328 }
2329 
checkSupport(Context & context) const2330 void Texture3DImageViewMinLodIntTexCoordTest::checkSupport(Context &context) const
2331 {
2332     DE_ASSERT(m_params.testType > util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD);
2333 
2334     context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2335     context.requireDeviceFunctionality("VK_EXT_robustness2");
2336     vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
2337     imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
2338     imageViewMinLodFeatures.pNext = DE_NULL;
2339 
2340     VkPhysicalDeviceRobustness2FeaturesEXT robustness2Features;
2341     robustness2Features.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
2342     robustness2Features.pNext = &imageViewMinLodFeatures;
2343     vk::VkPhysicalDeviceFeatures2 features2;
2344 
2345     features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
2346     features2.pNext = &robustness2Features;
2347 
2348     context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2349 
2350     if (imageViewMinLodFeatures.minLod == false)
2351         TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
2352 
2353     if (robustness2Features.robustImageAccess2 == false)
2354         TCU_THROW(NotSupportedError, "VK_EXT_robustness2 robustImageAccess2 feature not supported");
2355 }
2356 
createInstance(Context & context) const2357 TestInstance *Texture3DImageViewMinLodIntTexCoordTest::createInstance(Context &context) const
2358 {
2359     if (m_params.testType == util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD)
2360         return new Texture3DImageViewMinLodIntTexCoordTestInstance(context, m_params);
2361     else
2362         return new Texture3DImageViewMinLodBaseLevelIntTexCoordTestInstance(context, m_params);
2363 }
2364 
2365 // Texture gather tests.
2366 enum class GatherMinLod
2367 {
2368     MINLOD_0_1, // 0.1
2369     MINLOD_1_1, // 1.1
2370 };
2371 
2372 struct GatherParams
2373 {
2374     uint32_t randomSeed; // Seed for the pseudorandom number generator.
2375     GatherMinLod minLod; // Idea: make it 0.1 or 1.1
2376     int component;       // 0, 1, 2, 3 for the gather operation.
2377 
getNumericMinLodvkt::texture::__anonf5bf78d20111::GatherParams2378     float getNumericMinLod(void) const
2379     {
2380         float lod = 0.0f;
2381 
2382         switch (minLod)
2383         {
2384         case GatherMinLod::MINLOD_0_1:
2385             lod = 0.1f;
2386             break;
2387         case GatherMinLod::MINLOD_1_1:
2388             lod = 1.1f;
2389             break;
2390         default:
2391             DE_ASSERT(false);
2392             break;
2393         }
2394 
2395         return lod;
2396     }
2397 
getMinLodIntegervkt::texture::__anonf5bf78d20111::GatherParams2398     uint32_t getMinLodInteger(void) const
2399     {
2400         uint32_t lod = 0u;
2401 
2402         switch (minLod)
2403         {
2404         case GatherMinLod::MINLOD_0_1:
2405             lod = 0u;
2406             break;
2407         case GatherMinLod::MINLOD_1_1:
2408             lod = 1u;
2409             break;
2410         default:
2411             DE_ASSERT(false);
2412             break;
2413         }
2414 
2415         return lod;
2416     }
2417 
needsRobustness2vkt::texture::__anonf5bf78d20111::GatherParams2418     bool needsRobustness2(void) const
2419     {
2420         return (getNumericMinLod() >= 1.0f);
2421     }
2422 };
2423 
2424 class TextureGatherMinLodTest : public vkt::TestCase
2425 {
2426 public:
TextureGatherMinLodTest(tcu::TestContext & testCtx,const std::string & name,const GatherParams & params)2427     TextureGatherMinLodTest(tcu::TestContext &testCtx, const std::string &name, const GatherParams &params)
2428         : vkt::TestCase(testCtx, name)
2429         , m_params(params)
2430     {
2431     }
~TextureGatherMinLodTest(void)2432     virtual ~TextureGatherMinLodTest(void)
2433     {
2434     }
2435 
2436     void initPrograms(vk::SourceCollections &programCollection) const override;
2437     TestInstance *createInstance(Context &context) const override;
2438     void checkSupport(Context &context) const override;
2439 
2440 protected:
2441     GatherParams m_params;
2442 };
2443 
2444 class TextureGatherMinLodInstance : public vkt::TestInstance
2445 {
2446 public:
TextureGatherMinLodInstance(Context & context,const GatherParams & params)2447     TextureGatherMinLodInstance(Context &context, const GatherParams &params)
2448         : vkt::TestInstance(context)
2449         , m_params(params)
2450     {
2451     }
~TextureGatherMinLodInstance(void)2452     virtual ~TextureGatherMinLodInstance(void)
2453     {
2454     }
2455 
2456     tcu::TestStatus iterate(void) override;
2457 
2458 protected:
2459     GatherParams m_params;
2460 };
2461 
2462 // Test idea: create texture with 3 levels, each of them having a unique nonzero color. Render gathering the color from a fixed
2463 // position in that texture (center point). Use the minLod parameter when creating the view to control which one should be the
2464 // output color. If minLod is 0.1, minLodInteger should be 0 and gathering from the base level is defined, so we should get the
2465 // output color from the base level. If minLod is 1.1, gathering texels from the base level requires robustness2 and will result in
2466 // zeros instead of the color from levels 0 or 1.
initPrograms(vk::SourceCollections & programCollection) const2467 void TextureGatherMinLodTest::initPrograms(vk::SourceCollections &programCollection) const
2468 {
2469     // Full screen triangle covering the whole viewport.
2470     std::ostringstream vert;
2471     vert << "#version 450\n"
2472          << "\n"
2473          << "vec2 positions[3] = vec2[](\n"
2474          << "    vec2(-1.0, -1.0),\n"
2475          << "    vec2(3.0, -1.0),\n"
2476          << "    vec2(-1.0, 3.0)\n"
2477          << ");\n"
2478          << "\n"
2479          << "void main (void)\n"
2480          << "{\n"
2481          << "    gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0);\n"
2482          << "}\n";
2483     programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
2484 
2485     std::ostringstream frag;
2486     frag << "#version 450\n"
2487          << "\n"
2488          << "layout (location=0) out vec4 outColor;\n"
2489          << "layout (set=0, binding=0) uniform sampler2D u_sampler;\n"
2490          << "\n"
2491          << "void main (void)\n"
2492          << "{\n"
2493          << "    const vec2 gatherCoords = vec2(0.5, 0.5);\n"
2494          << "    const vec4 gatherRes = textureGather(u_sampler, gatherCoords, " << m_params.component << ");\n"
2495          << "    outColor = vec4(gatherRes.xyz, 1.0);\n"
2496          << "}\n";
2497     ;
2498     programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
2499 }
2500 
checkSupport(Context & context) const2501 void TextureGatherMinLodTest::checkSupport(Context &context) const
2502 {
2503     context.requireInstanceFunctionality("VK_KHR_get_physical_device_properties2");
2504     context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2505 
2506     if (m_params.needsRobustness2())
2507     {
2508         context.requireDeviceFunctionality("VK_EXT_robustness2");
2509 
2510         VkPhysicalDeviceRobustness2FeaturesEXT robustness2Features = initVulkanStructure();
2511         VkPhysicalDeviceFeatures2 features2                        = initVulkanStructure(&robustness2Features);
2512 
2513         context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2514 
2515         if (robustness2Features.robustImageAccess2 == false)
2516             TCU_THROW(NotSupportedError, "robustImageAccess2 not supported");
2517     }
2518 }
2519 
createInstance(Context & context) const2520 TestInstance *TextureGatherMinLodTest::createInstance(Context &context) const
2521 {
2522     return new TextureGatherMinLodInstance(context, m_params);
2523 }
2524 
2525 // Device helper: this is needed because we sometimes need a custom device with robustImageAccess2.
2526 class DeviceHelper
2527 {
2528 public:
~DeviceHelper()2529     virtual ~DeviceHelper()
2530     {
2531     }
2532     virtual const DeviceInterface &getDeviceInterface(void) const = 0;
2533     virtual VkDevice getDevice(void) const                        = 0;
2534     virtual uint32_t getQueueFamilyIndex(void) const              = 0;
2535     virtual VkQueue getQueue(void) const                          = 0;
2536     virtual Allocator &getAllocator(void) const                   = 0;
2537 };
2538 
2539 // This one just reuses the default device from the context.
2540 class ContextDeviceHelper : public DeviceHelper
2541 {
2542 public:
ContextDeviceHelper(Context & context)2543     ContextDeviceHelper(Context &context)
2544         : m_deviceInterface(context.getDeviceInterface())
2545         , m_device(context.getDevice())
2546         , m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
2547         , m_queue(context.getUniversalQueue())
2548         , m_allocator(context.getDefaultAllocator())
2549     {
2550     }
2551 
~ContextDeviceHelper()2552     virtual ~ContextDeviceHelper()
2553     {
2554     }
2555 
getDeviceInterface(void) const2556     const DeviceInterface &getDeviceInterface(void) const override
2557     {
2558         return m_deviceInterface;
2559     }
getDevice(void) const2560     VkDevice getDevice(void) const override
2561     {
2562         return m_device;
2563     }
getQueueFamilyIndex(void) const2564     uint32_t getQueueFamilyIndex(void) const override
2565     {
2566         return m_queueFamilyIndex;
2567     }
getQueue(void) const2568     VkQueue getQueue(void) const override
2569     {
2570         return m_queue;
2571     }
getAllocator(void) const2572     Allocator &getAllocator(void) const override
2573     {
2574         return m_allocator;
2575     }
2576 
2577 protected:
2578     const DeviceInterface &m_deviceInterface;
2579     const VkDevice m_device;
2580     const uint32_t m_queueFamilyIndex;
2581     const VkQueue m_queue;
2582     Allocator &m_allocator;
2583 };
2584 
2585 // This one creates a new device with robustImageAccess2.
2586 class RobustImageAccess2DeviceHelper : public DeviceHelper
2587 {
2588 public:
RobustImageAccess2DeviceHelper(Context & context)2589     RobustImageAccess2DeviceHelper(Context &context)
2590     {
2591         const auto &vkp           = context.getPlatformInterface();
2592         const auto &vki           = context.getInstanceInterface();
2593         const auto instance       = context.getInstance();
2594         const auto physicalDevice = context.getPhysicalDevice();
2595         const auto queuePriority  = 1.0f;
2596 
2597         // Queue index first.
2598         m_queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2599 
2600         // Create a universal queue that supports graphics and compute.
2601         const VkDeviceQueueCreateInfo queueParams = {
2602             VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
2603             DE_NULL,                                    // const void* pNext;
2604             0u,                                         // VkDeviceQueueCreateFlags flags;
2605             m_queueFamilyIndex,                         // uint32_t queueFamilyIndex;
2606             1u,                                         // uint32_t queueCount;
2607             &queuePriority                              // const float* pQueuePriorities;
2608         };
2609 
2610         const char *extensions[] = {
2611             "VK_EXT_robustness2",
2612             "VK_EXT_image_view_min_lod",
2613         };
2614 
2615         VkPhysicalDeviceImageViewMinLodFeaturesEXT minLodfeatures  = initVulkanStructure();
2616         VkPhysicalDeviceRobustness2FeaturesEXT robustness2Features = initVulkanStructure(&minLodfeatures);
2617         VkPhysicalDeviceFeatures2 features2                        = initVulkanStructure(&robustness2Features);
2618 
2619         vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
2620 
2621         const VkDeviceCreateInfo deviceCreateInfo = {
2622             VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,               //sType;
2623             &features2,                                         //pNext;
2624             0u,                                                 //flags
2625             1u,                                                 //queueRecordCount;
2626             &queueParams,                                       //pRequestedQueues;
2627             0u,                                                 //layerCount;
2628             nullptr,                                            //ppEnabledLayerNames;
2629             static_cast<uint32_t>(de::arrayLength(extensions)), // uint32_t enabledExtensionCount;
2630             extensions,                                         // const char* const* ppEnabledExtensionNames;
2631             nullptr,                                            //pEnabledFeatures;
2632         };
2633 
2634         m_device = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), vkp, instance,
2635                                       vki, physicalDevice, &deviceCreateInfo);
2636         m_vkd.reset(new DeviceDriver(vkp, instance, m_device.get(), context.getUsedApiVersion(),
2637                                      context.getTestContext().getCommandLine()));
2638         m_queue = getDeviceQueue(*m_vkd, *m_device, m_queueFamilyIndex, 0u);
2639         m_allocator.reset(
2640             new SimpleAllocator(*m_vkd, m_device.get(), getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
2641     }
2642 
~RobustImageAccess2DeviceHelper()2643     virtual ~RobustImageAccess2DeviceHelper()
2644     {
2645     }
2646 
getDeviceInterface(void) const2647     const DeviceInterface &getDeviceInterface(void) const override
2648     {
2649         return *m_vkd;
2650     }
getDevice(void) const2651     VkDevice getDevice(void) const override
2652     {
2653         return m_device.get();
2654     }
getQueueFamilyIndex(void) const2655     uint32_t getQueueFamilyIndex(void) const override
2656     {
2657         return m_queueFamilyIndex;
2658     }
getQueue(void) const2659     VkQueue getQueue(void) const override
2660     {
2661         return m_queue;
2662     }
getAllocator(void) const2663     Allocator &getAllocator(void) const override
2664     {
2665         return *m_allocator;
2666     }
2667 
2668 protected:
2669     Move<VkDevice> m_device;
2670     std::unique_ptr<DeviceDriver> m_vkd;
2671     uint32_t m_queueFamilyIndex;
2672     VkQueue m_queue;
2673     std::unique_ptr<SimpleAllocator> m_allocator;
2674 };
2675 
2676 std::unique_ptr<DeviceHelper> g_robustness2DeviceHelper;
2677 std::unique_ptr<DeviceHelper> g_contextDeviceHelper;
2678 
getDeviceHelper(Context & context,bool needsRobustness2)2679 DeviceHelper &getDeviceHelper(Context &context, bool needsRobustness2)
2680 {
2681     if (needsRobustness2)
2682     {
2683         if (!g_robustness2DeviceHelper)
2684             g_robustness2DeviceHelper.reset(new RobustImageAccess2DeviceHelper(context));
2685         return *g_robustness2DeviceHelper;
2686     }
2687 
2688     if (!g_contextDeviceHelper)
2689         g_contextDeviceHelper.reset(new ContextDeviceHelper(context));
2690     return *g_contextDeviceHelper;
2691 }
2692 
2693 // Cleanup function for the test group.
destroyDeviceHelpers(tcu::TestCaseGroup *)2694 void destroyDeviceHelpers(tcu::TestCaseGroup *)
2695 {
2696     g_robustness2DeviceHelper.reset(nullptr);
2697     g_contextDeviceHelper.reset(nullptr);
2698 }
2699 
iterate(void)2700 tcu::TestStatus TextureGatherMinLodInstance::iterate(void)
2701 {
2702     const auto &deviceHelper = getDeviceHelper(m_context, m_params.needsRobustness2());
2703     const auto &vkd          = deviceHelper.getDeviceInterface();
2704     const auto device        = deviceHelper.getDevice();
2705     const auto queueIndex    = deviceHelper.getQueueFamilyIndex();
2706     const auto queue         = deviceHelper.getQueue();
2707     auto &alloc              = deviceHelper.getAllocator();
2708 
2709     const auto imageFormat = VK_FORMAT_R8G8B8A8_UNORM;
2710     const auto tcuFormat   = mapVkFormat(imageFormat);
2711     const auto colorExtent = makeExtent3D(1u, 1u, 1u);
2712     const tcu::IVec3 iColorExtent(static_cast<int>(colorExtent.width), static_cast<int>(colorExtent.height),
2713                                   static_cast<int>(colorExtent.depth));
2714     const auto texExtent    = makeExtent3D(8u, 8u, 1u);
2715     const auto texMipLevels = 3u;
2716     const auto colorUsage =
2717         (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
2718     const auto texUsage =
2719         (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
2720     const auto minLodF = m_params.getNumericMinLod();
2721     const auto minLodU = m_params.getMinLodInteger();
2722     const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
2723 
2724     // Color attachment: a simple 1x1 image.
2725     const VkImageCreateInfo colorCreateInfo = {
2726         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
2727         nullptr,                             // const void* pNext;
2728         0u,                                  // VkImageCreateFlags flags;
2729         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
2730         imageFormat,                         // VkFormat format;
2731         colorExtent,                         // VkExtent3D extent;
2732         1u,                                  // uint32_t mipLevels;
2733         1u,                                  // uint32_t arrayLayers;
2734         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
2735         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
2736         colorUsage,                          // VkImageUsageFlags usage;
2737         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
2738         0u,                                  // uint32_t queueFamilyIndexCount;
2739         nullptr,                             // const uint32_t* pQueueFamilyIndices;
2740         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
2741     };
2742 
2743     ImageWithMemory colorBuffer(vkd, device, alloc, colorCreateInfo, MemoryRequirement::Any);
2744     const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
2745     const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2746     const auto colorBufferView =
2747         makeImageView(vkd, device, colorBuffer.get(), VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR);
2748 
2749     // Texture: an 8x8 image with several mip levels.
2750     const VkImageCreateInfo texCreateInfo = {
2751         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
2752         nullptr,                             // const void* pNext;
2753         0u,                                  // VkImageCreateFlags flags;
2754         VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
2755         imageFormat,                         // VkFormat format;
2756         texExtent,                           // VkExtent3D extent;
2757         texMipLevels,                        // uint32_t mipLevels;
2758         1u,                                  // uint32_t arrayLayers;
2759         VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
2760         VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
2761         texUsage,                            // VkImageUsageFlags usage;
2762         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
2763         0u,                                  // uint32_t queueFamilyIndexCount;
2764         nullptr,                             // const uint32_t* pQueueFamilyIndices;
2765         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
2766     };
2767 
2768     ImageWithMemory texture(vkd, device, alloc, texCreateInfo, MemoryRequirement::Any);
2769     const auto texSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, texMipLevels, 0u, 1u);
2770 
2771     DE_ASSERT(texMipLevels > 0u);
2772     DE_ASSERT(minLodU < texMipLevels);
2773 
2774     const VkImageViewMinLodCreateInfoEXT texMinLodInfo = {
2775         VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT, // VkStructureType sType;
2776         nullptr,                                              // const void* pNext;
2777         minLodF,                                              // float minLod;
2778     };
2779 
2780     const VkImageViewCreateInfo texViewCreateInfo = {
2781         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
2782         &texMinLodInfo,                           // const void* pNext;
2783         0u,                                       // VkImageViewCreateFlags flags;
2784         texture.get(),                            // VkImage image;
2785         VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType viewType;
2786         imageFormat,                              // VkFormat format;
2787         makeComponentMappingRGBA(),               // VkComponentMapping components;
2788         texSRR,                                   // VkImageSubresourceRange subresourceRange;
2789     };
2790 
2791     const auto texView = createImageView(vkd, device, &texViewCreateInfo);
2792 
2793     // Verification buffer for the color attachment.
2794     const auto verifBufferSize = static_cast<VkDeviceSize>(iColorExtent.x() * iColorExtent.y() * iColorExtent.z() *
2795                                                            tcu::getPixelSize(tcuFormat));
2796     const auto verifBufferCreateInfo = makeBufferCreateInfo(verifBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
2797     BufferWithMemory verifBuffer(vkd, device, alloc, verifBufferCreateInfo, MemoryRequirement::HostVisible);
2798     auto &verifBufferAlloc = verifBuffer.getAllocation();
2799     void *verifBufferData  = verifBufferAlloc.getHostPtr();
2800 
2801     // Descriptor set layout.
2802     DescriptorSetLayoutBuilder setLayoutBuilder;
2803     setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
2804     const auto setLayout = setLayoutBuilder.build(vkd, device);
2805 
2806     // Pipeline layout.
2807     const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());
2808 
2809     // Sampler.
2810     const VkSamplerCreateInfo samplerCreateInfo = {
2811         VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType;
2812         nullptr,                               // const void* pNext;
2813         0u,                                    // VkSamplerCreateFlags flags;
2814         VK_FILTER_LINEAR,                      // VkFilter magFilter;
2815         VK_FILTER_LINEAR,                      // VkFilter minFilter;
2816         VK_SAMPLER_MIPMAP_MODE_LINEAR,         // VkSamplerMipmapMode mipmapMode;
2817         VK_SAMPLER_ADDRESS_MODE_REPEAT,        // VkSamplerAddressMode addressModeU;
2818         VK_SAMPLER_ADDRESS_MODE_REPEAT,        // VkSamplerAddressMode addressModeV;
2819         VK_SAMPLER_ADDRESS_MODE_REPEAT,        // VkSamplerAddressMode addressModeW;
2820         0.0f,                                  // float mipLodBias;
2821         VK_FALSE,                              // VkBool32 anisotropyEnable;
2822         0.0f,                                  // float maxAnisotropy;
2823         VK_FALSE,                              // VkBool32 compareEnable;
2824         VK_COMPARE_OP_NEVER,                   // VkCompareOp compareOp;
2825         0.0f,                                  // float minLod;
2826         static_cast<float>(texMipLevels),      // float maxLod;
2827         VK_BORDER_COLOR_INT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
2828         VK_FALSE,                              // VkBool32 unnormalizedCoordinates;
2829     };
2830     const auto sampler = createSampler(vkd, device, &samplerCreateInfo);
2831 
2832     // Descriptor pool and set.
2833     DescriptorPoolBuilder poolBuilder;
2834     poolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
2835     const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2836     const auto descriptorSet  = makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());
2837 
2838     // Update descriptor set.
2839     DescriptorSetUpdateBuilder setUpdateBuilder;
2840     const auto combinedSamplerInfo =
2841         makeDescriptorImageInfo(sampler.get(), texView.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2842     setUpdateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u),
2843                                  VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &combinedSamplerInfo);
2844     setUpdateBuilder.update(vkd, device);
2845 
2846     // Render pass and framebuffer.
2847     const auto renderPass = makeRenderPass(vkd, device, imageFormat);
2848     const auto framebuffer =
2849         makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), colorExtent.width, colorExtent.height);
2850 
2851     // Shader modules.
2852     const auto &binaries  = m_context.getBinaryCollection();
2853     const auto vertModule = createShaderModule(vkd, device, binaries.get("vert"));
2854     const auto fragModule = createShaderModule(vkd, device, binaries.get("frag"));
2855 
2856     // Viewports and scissors.
2857     std::vector<VkViewport> viewports(1u, makeViewport(colorExtent));
2858     std::vector<VkRect2D> scissors(1u, makeRect2D(colorExtent));
2859 
2860     // Pipeline.
2861     const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
2862 
2863     const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(), vertModule.get(), DE_NULL, DE_NULL,
2864                                                DE_NULL, fragModule.get(), renderPass.get(), viewports, scissors,
2865                                                VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u /*subpass*/,
2866                                                0u /*patchControlPoints*/, &vertexInputState);
2867 
2868     // Command pool and buffer.
2869     const auto cmdPool      = makeCommandPool(vkd, device, queueIndex);
2870     const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2871     const auto cmdBuffer    = cmdBufferPtr.get();
2872 
2873     beginCommandBuffer(vkd, cmdBuffer);
2874 
2875     // Move the whole texture to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
2876     const auto preClearBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2877                                                         VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture.get(), texSRR);
2878     cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2879                                   &preClearBarrier);
2880 
2881     // Fill each texture mip level with a different pseudorandom nonzero color.
2882     std::vector<tcu::Vec4> levelColors;
2883     de::Random rnd(m_params.randomSeed);
2884 
2885     levelColors.reserve(texMipLevels);
2886 
2887     const auto minColor = 0.004f; // Slightly above 1/255.
2888     const auto maxColor = 1.0f;
2889 
2890     for (uint32_t level = 0u; level < texMipLevels; ++level)
2891     {
2892         const auto r          = rnd.getFloat(minColor, maxColor);
2893         const auto g          = rnd.getFloat(minColor, maxColor);
2894         const auto b          = rnd.getFloat(minColor, maxColor);
2895         const auto a          = rnd.getFloat(minColor, maxColor);
2896         const auto levelColor = makeClearValueColorF32(r, g, b, a).color;
2897         const auto levelRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, level, 1u, 0u, 1u);
2898 
2899         levelColors.emplace_back(r, g, b, a);
2900         vkd.cmdClearColorImage(cmdBuffer, texture.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &levelColor, 1u,
2901                                &levelRange);
2902     }
2903 
2904     // Move the whole texture to VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
2905     const auto postClearBarrier = makeImageMemoryBarrier(
2906         VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2907         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, texture.get(), texSRR);
2908     cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
2909                                   &postClearBarrier);
2910 
2911     beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0u), clearColor);
2912     vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u,
2913                               &descriptorSet.get(), 0u, nullptr);
2914     vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
2915     vkd.cmdDraw(cmdBuffer, 3u, 1u, 0u, 0u); // This has to match the vertex shader.
2916     endRenderPass(vkd, cmdBuffer);
2917 
2918     // Copy color buffer to verification buffer.
2919     const auto postColorBarier = makeImageMemoryBarrier(
2920         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
2921         VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, colorBuffer.get(), colorSRR);
2922     cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
2923                                   VK_PIPELINE_STAGE_TRANSFER_BIT, &postColorBarier);
2924 
2925     const auto copyRegion = makeBufferImageCopy(colorExtent, colorSRL);
2926     vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, verifBuffer.get(), 1u,
2927                              &copyRegion);
2928 
2929     const auto preHostBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
2930     cmdPipelineMemoryBarrier(vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT,
2931                              &preHostBarrier);
2932 
2933     endCommandBuffer(vkd, cmdBuffer);
2934     submitCommandsAndWait(vkd, device, queue, cmdBuffer);
2935 
2936     // Verify color buffer.
2937     invalidateAlloc(vkd, device, verifBufferAlloc);
2938     tcu::ConstPixelBufferAccess resultAccess(tcuFormat, iColorExtent, verifBufferData);
2939 
2940     const auto resultColor   = resultAccess.getPixel(0, 0);
2941     const auto srcLevelColor = levelColors.at(minLodU);
2942     const auto compColor     = srcLevelColor[m_params.component];
2943     const auto expectedColor = (m_params.needsRobustness2() // This has to match the fragment shader.
2944                                     ?
2945                                     tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) :
2946                                     tcu::Vec4(compColor, compColor, compColor, 1.0f));
2947     const auto threshold     = (m_params.needsRobustness2() ? 0.0f : 0.005f); // 1/255 < 0.005 < 2/255
2948 
2949     const auto diff = abs(resultColor - expectedColor);
2950     const tcu::Vec4 thresholdVec(threshold, threshold, threshold, 0.0f);
2951     const auto thresholdMet = tcu::lessThanEqual(diff, thresholdVec);
2952 
2953     if (!tcu::boolAll(thresholdMet))
2954     {
2955         std::ostringstream msg;
2956         msg << "Unexpected output buffer color: expected " << expectedColor << " but found " << resultColor
2957             << " [diff=" << diff << "]";
2958         TCU_FAIL(msg.str());
2959     }
2960 
2961     return tcu::TestStatus::pass("Pass");
2962 }
2963 
2964 #endif // CTS_USES_VULKANSC
2965 
2966 } // namespace
2967 
2968 #ifndef CTS_USES_VULKANSC
2969 
2970 namespace util
2971 {
2972 
2973 template <>
checkTextureSupport(Context & context,const Texture2DMipmapTestCaseParameters & testParameters)2974 void checkTextureSupport(Context &context, const Texture2DMipmapTestCaseParameters &testParameters)
2975 {
2976     if (testParameters.testType != TextureCommonTestCaseParameters::TEST_NORMAL)
2977     {
2978         context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2979         vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
2980         imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
2981         imageViewMinLodFeatures.pNext = DE_NULL;
2982 
2983         vk::VkPhysicalDeviceFeatures2 features2;
2984 
2985         features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
2986         features2.pNext = &imageViewMinLodFeatures;
2987 
2988         context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
2989 
2990         if (imageViewMinLodFeatures.minLod == false)
2991             TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
2992     }
2993 }
2994 
2995 template <>
checkTextureSupport(Context & context,const TextureCubeMipmapTestCaseParameters & testParameters)2996 void checkTextureSupport(Context &context, const TextureCubeMipmapTestCaseParameters &testParameters)
2997 {
2998     if (testParameters.testType != TextureCommonTestCaseParameters::TEST_NORMAL)
2999     {
3000         context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
3001         vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
3002         imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
3003         imageViewMinLodFeatures.pNext = DE_NULL;
3004 
3005         vk::VkPhysicalDeviceFeatures2 features2;
3006 
3007         features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
3008         features2.pNext = &imageViewMinLodFeatures;
3009 
3010         context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
3011 
3012         if (imageViewMinLodFeatures.minLod == false)
3013             TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
3014     }
3015 }
3016 
3017 template <>
checkTextureSupport(Context & context,const Texture3DMipmapTestCaseParameters & testParameters)3018 void checkTextureSupport(Context &context, const Texture3DMipmapTestCaseParameters &testParameters)
3019 {
3020     if (testParameters.testType != TextureCommonTestCaseParameters::TEST_NORMAL)
3021     {
3022         context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
3023         vk::VkPhysicalDeviceImageViewMinLodFeaturesEXT imageViewMinLodFeatures;
3024         imageViewMinLodFeatures.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_MIN_LOD_FEATURES_EXT;
3025         imageViewMinLodFeatures.pNext = DE_NULL;
3026 
3027         vk::VkPhysicalDeviceFeatures2 features2;
3028 
3029         features2.sType = vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
3030         features2.pNext = &imageViewMinLodFeatures;
3031 
3032         context.getInstanceInterface().getPhysicalDeviceFeatures2(context.getPhysicalDevice(), &features2);
3033 
3034         if (imageViewMinLodFeatures.minLod == false)
3035             TCU_THROW(NotSupportedError, "VK_EXT_image_view_min_lod minLod feature not supported");
3036     }
3037 }
3038 
3039 } // namespace util
3040 
populateMinLodGatherGroup(tcu::TestCaseGroup * minLodGatherGroup)3041 void populateMinLodGatherGroup(tcu::TestCaseGroup *minLodGatherGroup)
3042 {
3043     using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
3044 
3045     const struct
3046     {
3047         GatherMinLod minLod;
3048         const char *name;
3049     } GatherMinLodCases[] = {
3050         {GatherMinLod::MINLOD_0_1, "minlod_0_1"},
3051         {GatherMinLod::MINLOD_1_1, "minlod_1_1"},
3052     };
3053 
3054     const struct
3055     {
3056         int component;
3057         const char *name;
3058     } ComponentCases[] = {
3059         {0, "component_0"},
3060         {1, "component_1"},
3061         {2, "component_2"},
3062         {3, "component_3"},
3063     };
3064 
3065     auto &testCtx = minLodGatherGroup->getTestContext();
3066 
3067     for (const auto &gatherMinLodCase : GatherMinLodCases)
3068     {
3069         GroupPtr minLodGroup(new tcu::TestCaseGroup(testCtx, gatherMinLodCase.name));
3070 
3071         for (const auto &componentCase : ComponentCases)
3072         {
3073             const uint32_t seed = (static_cast<uint32_t>(gatherMinLodCase.minLod) + 1000u) * 1000u +
3074                                   (static_cast<uint32_t>(componentCase.component) + 1000u);
3075 
3076             GatherParams params;
3077             params.randomSeed = seed;
3078             params.minLod     = gatherMinLodCase.minLod;
3079             params.component  = componentCase.component;
3080 
3081             minLodGroup->addChild(new TextureGatherMinLodTest(testCtx, componentCase.name, params));
3082         }
3083 
3084         minLodGatherGroup->addChild(minLodGroup.release());
3085     }
3086 }
3087 
3088 #endif // CTS_USES_VULKANSC
3089 
populateTextureMipmappingTests(tcu::TestCaseGroup * textureMipmappingTests)3090 void populateTextureMipmappingTests(tcu::TestCaseGroup *textureMipmappingTests)
3091 {
3092     tcu::TestContext &testCtx = textureMipmappingTests->getTestContext();
3093 
3094     static const struct
3095     {
3096         const char *name;
3097         const Sampler::WrapMode mode;
3098     } wrapModes[] = {
3099         {"clamp", Sampler::CLAMP_TO_EDGE}, {"repeat", Sampler::REPEAT_GL}, {"mirror", Sampler::MIRRORED_REPEAT_GL}};
3100 
3101     static const struct
3102     {
3103         const char *name;
3104         const Sampler::FilterMode mode;
3105     } minFilterModes[] = {{"nearest_nearest", Sampler::NEAREST_MIPMAP_NEAREST},
3106                           {"linear_nearest", Sampler::LINEAR_MIPMAP_NEAREST},
3107                           {"nearest_linear", Sampler::NEAREST_MIPMAP_LINEAR},
3108                           {"linear_linear", Sampler::LINEAR_MIPMAP_LINEAR}};
3109 
3110     static const struct
3111     {
3112         const char *name;
3113         const Sampler::FilterMode mode;
3114     } magFilterModes[] = {{"nearest", Sampler::NEAREST}, {"linear", Sampler::LINEAR}};
3115 
3116     static const struct
3117     {
3118         const CoordType type;
3119         const char *name;
3120     } coordTypes[] = {// Mipmapping with translated and scaled coordinates
3121                       {COORDTYPE_BASIC, "basic"},
3122                       // Mipmapping with affine coordinate transform
3123                       {COORDTYPE_AFFINE, "affine"},
3124                       // Mipmapping with perspective projection
3125                       {COORDTYPE_PROJECTED, "projected"}};
3126 
3127     static const struct
3128     {
3129         const char *name;
3130         const int width;
3131         const int height;
3132     } tex2DSizes[] = {{DE_NULL, 64, 64}, // Default.
3133                       {"npot", 63, 57},
3134                       {"non_square", 32, 64}};
3135 
3136     static const struct
3137     {
3138         const char *name;
3139         const int width;
3140         const int height;
3141         const int depth;
3142     } tex3DSizes[] = {{DE_NULL, 32, 32, 32}, // Default.
3143                       {"npot", 33, 29, 27}};
3144 
3145     const int cubeMapSize = 64;
3146 
3147     static const struct
3148     {
3149         const CoordType type;
3150         const char *name;
3151     } cubeCoordTypes[] = {// Mipmapping with translated and scaled coordinates
3152                           {COORDTYPE_BASIC, "basic"},
3153                           // Mipmapping with perspective projection
3154                           {COORDTYPE_PROJECTED, "projected"},
3155                           // User-supplied bias value
3156                           {COORDTYPE_BASIC_BIAS, "bias"}};
3157 
3158     // 2D cases.
3159     {
3160         // 2D Mipmap Filtering
3161         de::MovePtr<tcu::TestCaseGroup> group2D(new tcu::TestCaseGroup(testCtx, "2d"));
3162 
3163         // User-supplied bias value
3164         de::MovePtr<tcu::TestCaseGroup> biasGroup2D(new tcu::TestCaseGroup(testCtx, "bias"));
3165         de::MovePtr<tcu::TestCaseGroup> minLodGroup2D(new tcu::TestCaseGroup(testCtx, "min_lod"));
3166         de::MovePtr<tcu::TestCaseGroup> maxLodGroup2D(new tcu::TestCaseGroup(testCtx, "max_lod"));
3167         de::MovePtr<tcu::TestCaseGroup> baseLevelGroup2D(new tcu::TestCaseGroup(testCtx, "base_level"));
3168         de::MovePtr<tcu::TestCaseGroup> maxLevelGroup2D(new tcu::TestCaseGroup(testCtx, "max_level"));
3169 
3170 #ifndef CTS_USES_VULKANSC
3171         de::MovePtr<tcu::TestCaseGroup> imageViewMinLodExtGroup2D(
3172             new tcu::TestCaseGroup(testCtx, "image_view_min_lod"));
3173         de::MovePtr<tcu::TestCaseGroup> imageViewMinLodGroup2D(new tcu::TestCaseGroup(testCtx, "min_lod"));
3174         de::MovePtr<tcu::TestCaseGroup> imageViewMinLodBaseLevelGroup2D(new tcu::TestCaseGroup(testCtx, "base_level"));
3175 #endif // CTS_USES_VULKANSC
3176 
3177         for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
3178         {
3179             de::MovePtr<tcu::TestCaseGroup> coordTypeGroup(new tcu::TestCaseGroup(testCtx, coordTypes[coordType].name));
3180 
3181             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3182             {
3183                 for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
3184                 {
3185                     // Add non_square variants to basic cases only.
3186                     int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex2DSizes) : 1;
3187 
3188                     for (int size = 0; size < sizeEnd; size++)
3189                     {
3190                         Texture2DMipmapTestCaseParameters testParameters;
3191 
3192                         testParameters.coordType  = coordTypes[coordType].type;
3193                         testParameters.minFilter  = minFilterModes[minFilter].mode;
3194                         testParameters.wrapS      = wrapModes[wrapMode].mode;
3195                         testParameters.wrapT      = wrapModes[wrapMode].mode;
3196                         testParameters.format     = VK_FORMAT_R8G8B8A8_UNORM;
3197                         testParameters.width      = tex2DSizes[size].width;
3198                         testParameters.height     = tex2DSizes[size].height;
3199                         testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3200                         testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3201 
3202                         std::ostringstream name;
3203                         name << minFilterModes[minFilter].name << "_" << wrapModes[wrapMode].name;
3204 
3205                         if (tex2DSizes[size].name)
3206                             name << "_" << tex2DSizes[size].name;
3207 
3208                         coordTypeGroup->addChild(new TextureTestCase<Texture2DMipmapTestInstance>(
3209                             testCtx, name.str().c_str(), testParameters));
3210                     }
3211                 }
3212             }
3213 
3214             group2D->addChild(coordTypeGroup.release());
3215         }
3216 
3217         // 2D bias variants.
3218         {
3219             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3220             {
3221                 Texture2DMipmapTestCaseParameters testParameters;
3222 
3223                 testParameters.coordType  = COORDTYPE_BASIC_BIAS;
3224                 testParameters.minFilter  = minFilterModes[minFilter].mode;
3225                 testParameters.magFilter  = minFilterModes[minFilter].mode;
3226                 testParameters.wrapS      = Sampler::REPEAT_GL;
3227                 testParameters.wrapT      = Sampler::REPEAT_GL;
3228                 testParameters.format     = VK_FORMAT_R8G8B8A8_UNORM;
3229                 testParameters.width      = tex2DSizes[0].width;
3230                 testParameters.height     = tex2DSizes[0].height;
3231                 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3232                 testParameters.programs.push_back(PROGRAM_2D_FLOAT_BIAS);
3233 
3234                 std::ostringstream name;
3235                 name << minFilterModes[minFilter].name;
3236 
3237                 biasGroup2D->addChild(
3238                     new TextureTestCase<Texture2DMipmapTestInstance>(testCtx, name.str().c_str(), testParameters));
3239             }
3240         }
3241 
3242         // 2D LOD controls.
3243         {
3244             // MIN_LOD
3245             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3246             {
3247                 Texture2DMipmapTestCaseParameters testParameters;
3248                 testParameters.minFilter  = minFilterModes[minFilter].mode;
3249                 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3250                 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3251 
3252                 minLodGroup2D->addChild(new TextureTestCase<Texture2DMinLodTestInstance>(
3253                     testCtx, minFilterModes[minFilter].name, testParameters));
3254             }
3255 
3256             // MAX_LOD
3257             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3258             {
3259                 Texture2DMipmapTestCaseParameters testParameters;
3260                 testParameters.minFilter  = minFilterModes[minFilter].mode;
3261                 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3262                 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3263 
3264                 maxLodGroup2D->addChild(new TextureTestCase<Texture2DMaxLodTestInstance>(
3265                     testCtx, minFilterModes[minFilter].name, testParameters));
3266             }
3267         }
3268 
3269         {
3270             // BASE_LEVEL
3271             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3272             {
3273                 Texture2DMipmapTestCaseParameters testParameters;
3274                 testParameters.minFilter     = minFilterModes[minFilter].mode;
3275                 testParameters.minFilterName = minFilterModes[minFilter].name;
3276                 testParameters.aspectMask    = VK_IMAGE_ASPECT_COLOR_BIT;
3277                 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3278 
3279                 baseLevelGroup2D->addChild(new TextureTestCase<Texture2DBaseLevelTestInstance>(
3280                     testCtx, minFilterModes[minFilter].name, testParameters));
3281             }
3282 
3283             // MAX_LEVEL
3284             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3285             {
3286                 Texture2DMipmapTestCaseParameters testParameters;
3287                 testParameters.minFilter     = minFilterModes[minFilter].mode;
3288                 testParameters.minFilterName = minFilterModes[minFilter].name;
3289                 testParameters.aspectMask    = VK_IMAGE_ASPECT_COLOR_BIT;
3290                 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3291 
3292                 maxLevelGroup2D->addChild(new TextureTestCase<Texture2DMaxLevelTestInstance>(
3293                     testCtx, minFilterModes[minFilter].name, testParameters));
3294             }
3295         }
3296 
3297         // 2D VK_EXT_image_view_min_lod.
3298 #ifndef CTS_USES_VULKANSC
3299         {
3300             // MIN_LOD
3301             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3302             {
3303                 Texture2DMipmapTestCaseParameters testParameters;
3304                 testParameters.minFilter  = minFilterModes[minFilter].mode;
3305                 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3306                 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3307                 testParameters.testType = util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3308 
3309                 imageViewMinLodGroup2D->addChild(new TextureTestCase<Texture2DImageViewMinLodTestInstance>(
3310                     testCtx, minFilterModes[minFilter].name, testParameters));
3311 
3312                 std::ostringstream name;
3313                 name << minFilterModes[minFilter].name << "_integer_texel_coord";
3314                 testParameters.testType = util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD;
3315                 imageViewMinLodGroup2D->addChild(
3316                     new Texture2DImageViewMinLodIntTexCoordTest(testCtx, name.str().c_str(), testParameters));
3317             }
3318 
3319             // BASE_LEVEL
3320             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3321             {
3322                 Texture2DMipmapTestCaseParameters testParameters;
3323                 testParameters.minFilter     = minFilterModes[minFilter].mode;
3324                 testParameters.minFilterName = minFilterModes[minFilter].name;
3325                 testParameters.aspectMask    = VK_IMAGE_ASPECT_COLOR_BIT;
3326                 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
3327                 testParameters.testType = util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3328 
3329                 imageViewMinLodBaseLevelGroup2D->addChild(
3330                     new TextureTestCase<Texture2DImageViewMinLodBaseLevelTestInstance>(
3331                         testCtx, minFilterModes[minFilter].name, testParameters));
3332 
3333                 std::ostringstream name;
3334                 name << minFilterModes[minFilter].name << "_integer_texel_coord";
3335                 testParameters.testType =
3336                     util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD_BASELEVEL;
3337                 imageViewMinLodBaseLevelGroup2D->addChild(
3338                     new Texture2DImageViewMinLodIntTexCoordTest(testCtx, name.str().c_str(), testParameters));
3339             }
3340 
3341             imageViewMinLodExtGroup2D->addChild(imageViewMinLodGroup2D.release());
3342             imageViewMinLodExtGroup2D->addChild(imageViewMinLodBaseLevelGroup2D.release());
3343         }
3344 #endif // CTS_USES_VULKANSC
3345 
3346         group2D->addChild(biasGroup2D.release());
3347         group2D->addChild(minLodGroup2D.release());
3348         group2D->addChild(maxLodGroup2D.release());
3349         group2D->addChild(baseLevelGroup2D.release());
3350         group2D->addChild(maxLevelGroup2D.release());
3351 #ifndef CTS_USES_VULKANSC
3352         group2D->addChild(imageViewMinLodExtGroup2D.release());
3353 #endif // CTS_USES_VULKANSC
3354 
3355         textureMipmappingTests->addChild(group2D.release());
3356     }
3357 
3358     // Cubemap cases.
3359     {
3360         de::MovePtr<tcu::TestCaseGroup> groupCube(new tcu::TestCaseGroup(testCtx, "cubemap"));
3361 
3362         de::MovePtr<tcu::TestCaseGroup> minLodGroupCube(new tcu::TestCaseGroup(testCtx, "min_lod"));
3363         de::MovePtr<tcu::TestCaseGroup> maxLodGroupCube(new tcu::TestCaseGroup(testCtx, "max_lod"));
3364         de::MovePtr<tcu::TestCaseGroup> baseLevelGroupCube(new tcu::TestCaseGroup(testCtx, "base_level"));
3365         de::MovePtr<tcu::TestCaseGroup> maxLevelGroupCube(new tcu::TestCaseGroup(testCtx, "max_level"));
3366 
3367 #ifndef CTS_USES_VULKANSC
3368         de::MovePtr<tcu::TestCaseGroup> imageViewMinLodExtGroupCube(
3369             new tcu::TestCaseGroup(testCtx, "image_view_min_lod"));
3370         de::MovePtr<tcu::TestCaseGroup> imageViewMinLodGroupCube(new tcu::TestCaseGroup(testCtx, "min_lod"));
3371         de::MovePtr<tcu::TestCaseGroup> imageViewMinLodBaseLevelGroupCube(
3372             new tcu::TestCaseGroup(testCtx, "base_level"));
3373 #endif // CTS_USES_VULKANSC
3374 
3375         for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(cubeCoordTypes); coordType++)
3376         {
3377             de::MovePtr<tcu::TestCaseGroup> coordTypeGroup(
3378                 new tcu::TestCaseGroup(testCtx, cubeCoordTypes[coordType].name));
3379 
3380             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3381             {
3382                 for (int magFilter = 0; magFilter < DE_LENGTH_OF_ARRAY(magFilterModes); magFilter++)
3383                 {
3384                     for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
3385                     {
3386                         TextureCubeMipmapTestCaseParameters testParameters;
3387 
3388                         testParameters.coordType     = cubeCoordTypes[coordType].type;
3389                         testParameters.minFilter     = minFilterModes[minFilter].mode;
3390                         testParameters.magFilter     = magFilterModes[magFilter].mode;
3391                         testParameters.minFilterName = minFilterModes[minFilter].name;
3392                         testParameters.wrapS         = wrapModes[wrapMode].mode;
3393                         testParameters.wrapT         = wrapModes[wrapMode].mode;
3394                         testParameters.format        = VK_FORMAT_R8G8B8A8_UNORM;
3395                         testParameters.size          = cubeMapSize;
3396                         testParameters.aspectMask    = VK_IMAGE_ASPECT_COLOR_BIT;
3397 
3398                         if (testParameters.coordType == COORDTYPE_BASIC_BIAS)
3399                             testParameters.programs.push_back(PROGRAM_CUBE_FLOAT_BIAS);
3400                         else
3401                             testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3402 
3403                         std::ostringstream name;
3404                         name << minFilterModes[minFilter].name << "_" << magFilterModes[magFilter].name << "_"
3405                              << wrapModes[wrapMode].name;
3406 
3407                         coordTypeGroup->addChild(new TextureTestCase<TextureCubeMipmapTestInstance>(
3408                             testCtx, name.str().c_str(), testParameters));
3409                     }
3410                 }
3411             }
3412 
3413             groupCube->addChild(coordTypeGroup.release());
3414         }
3415 
3416         // Cubemap LOD controls.
3417         {
3418             // MIN_LOD
3419             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3420             {
3421                 TextureCubeMipmapTestCaseParameters testParameters;
3422                 testParameters.minFilter  = minFilterModes[minFilter].mode;
3423                 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3424                 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3425 
3426                 minLodGroupCube->addChild(new TextureTestCase<TextureCubeMinLodTestInstance>(
3427                     testCtx, minFilterModes[minFilter].name, testParameters));
3428             }
3429 
3430             // MAX_LOD
3431             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3432             {
3433                 TextureCubeMipmapTestCaseParameters testParameters;
3434                 testParameters.minFilter  = minFilterModes[minFilter].mode;
3435                 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3436                 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3437 
3438                 maxLodGroupCube->addChild(new TextureTestCase<TextureCubeMaxLodTestInstance>(
3439                     testCtx, minFilterModes[minFilter].name, testParameters));
3440             }
3441         }
3442 
3443         {
3444             // BASE_LEVEL
3445             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3446             {
3447                 TextureCubeMipmapTestCaseParameters testParameters;
3448                 testParameters.minFilter     = minFilterModes[minFilter].mode;
3449                 testParameters.minFilterName = minFilterModes[minFilter].name;
3450                 testParameters.aspectMask    = VK_IMAGE_ASPECT_COLOR_BIT;
3451                 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3452 
3453                 baseLevelGroupCube->addChild(new TextureTestCase<TextureCubeBaseLevelTestInstance>(
3454                     testCtx, minFilterModes[minFilter].name, testParameters));
3455             }
3456 
3457             // MAX_LEVEL
3458             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3459             {
3460                 TextureCubeMipmapTestCaseParameters testParameters;
3461                 testParameters.minFilter     = minFilterModes[minFilter].mode;
3462                 testParameters.minFilterName = minFilterModes[minFilter].name;
3463                 testParameters.aspectMask    = VK_IMAGE_ASPECT_COLOR_BIT;
3464                 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3465 
3466                 maxLevelGroupCube->addChild(new TextureTestCase<TextureCubeMaxLevelTestInstance>(
3467                     testCtx, minFilterModes[minFilter].name, testParameters));
3468             }
3469         }
3470 
3471         // Cube VK_EXT_image_view_min_lod.
3472 #ifndef CTS_USES_VULKANSC
3473         {
3474             // MIN_LOD
3475             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3476             {
3477                 TextureCubeMipmapTestCaseParameters testParameters;
3478                 testParameters.minFilter  = minFilterModes[minFilter].mode;
3479                 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3480                 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3481                 testParameters.testType = util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3482 
3483                 imageViewMinLodGroupCube->addChild(new TextureTestCase<TextureCubeImageViewMinLodTestInstance>(
3484                     testCtx, minFilterModes[minFilter].name, testParameters));
3485             }
3486 
3487             // BASE_LEVEL
3488             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3489             {
3490                 TextureCubeMipmapTestCaseParameters testParameters;
3491                 testParameters.minFilter     = minFilterModes[minFilter].mode;
3492                 testParameters.minFilterName = minFilterModes[minFilter].name;
3493                 testParameters.aspectMask    = VK_IMAGE_ASPECT_COLOR_BIT;
3494                 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
3495                 testParameters.testType = util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3496 
3497                 imageViewMinLodBaseLevelGroupCube->addChild(
3498                     new TextureTestCase<TextureCubeImageViewMinLodBaseLevelTestInstance>(
3499                         testCtx, minFilterModes[minFilter].name, testParameters));
3500             }
3501 
3502             imageViewMinLodExtGroupCube->addChild(imageViewMinLodGroupCube.release());
3503             imageViewMinLodExtGroupCube->addChild(imageViewMinLodBaseLevelGroupCube.release());
3504         }
3505 #endif // CTS_USES_VULKANSC
3506 
3507         groupCube->addChild(minLodGroupCube.release());
3508         groupCube->addChild(maxLodGroupCube.release());
3509         groupCube->addChild(baseLevelGroupCube.release());
3510         groupCube->addChild(maxLevelGroupCube.release());
3511 #ifndef CTS_USES_VULKANSC
3512         groupCube->addChild(imageViewMinLodExtGroupCube.release());
3513 #endif // CTS_USES_VULKANSC
3514 
3515         textureMipmappingTests->addChild(groupCube.release());
3516     }
3517 
3518     // 3D cases.
3519     {
3520         de::MovePtr<tcu::TestCaseGroup> group3D(new tcu::TestCaseGroup(testCtx, "3d"));
3521 
3522         de::MovePtr<tcu::TestCaseGroup> biasGroup3D(new tcu::TestCaseGroup(testCtx, "bias"));
3523         de::MovePtr<tcu::TestCaseGroup> minLodGroup3D(new tcu::TestCaseGroup(testCtx, "min_lod"));
3524         de::MovePtr<tcu::TestCaseGroup> maxLodGroup3D(new tcu::TestCaseGroup(testCtx, "max_lod"));
3525         de::MovePtr<tcu::TestCaseGroup> baseLevelGroup3D(new tcu::TestCaseGroup(testCtx, "base_level"));
3526         de::MovePtr<tcu::TestCaseGroup> maxLevelGroup3D(new tcu::TestCaseGroup(testCtx, "max_level"));
3527 
3528 #ifndef CTS_USES_VULKANSC
3529         de::MovePtr<tcu::TestCaseGroup> imageViewMinLodExtGroup3D(
3530             new tcu::TestCaseGroup(testCtx, "image_view_min_lod"));
3531         de::MovePtr<tcu::TestCaseGroup> imageViewMinLodGroup3D(new tcu::TestCaseGroup(testCtx, "min_lod"));
3532         de::MovePtr<tcu::TestCaseGroup> imageViewMinLodBaseLevelGroup3D(new tcu::TestCaseGroup(testCtx, "base_level"));
3533 #endif // CTS_USES_VULKANSC
3534 
3535         for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
3536         {
3537             de::MovePtr<tcu::TestCaseGroup> coordTypeGroup(new tcu::TestCaseGroup(testCtx, coordTypes[coordType].name));
3538 
3539             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3540             {
3541                 for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
3542                 {
3543                     // Add other size variants to basic cases only.
3544                     int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex3DSizes) : 1;
3545 
3546                     Texture3DMipmapTestCaseParameters testParameters;
3547 
3548                     testParameters.coordType     = coordTypes[coordType].type;
3549                     testParameters.minFilter     = minFilterModes[minFilter].mode;
3550                     testParameters.minFilterName = minFilterModes[minFilter].name;
3551                     testParameters.wrapR         = wrapModes[wrapMode].mode;
3552                     testParameters.wrapS         = wrapModes[wrapMode].mode;
3553                     testParameters.wrapT         = wrapModes[wrapMode].mode;
3554                     testParameters.format        = VK_FORMAT_R8G8B8A8_UNORM;
3555                     testParameters.aspectMask    = VK_IMAGE_ASPECT_COLOR_BIT;
3556                     testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3557 
3558                     for (int size = 0; size < sizeEnd; size++)
3559                     {
3560                         testParameters.width  = tex3DSizes[size].width;
3561                         testParameters.height = tex3DSizes[size].height;
3562                         testParameters.depth  = tex3DSizes[size].depth;
3563 
3564                         std::ostringstream name;
3565                         name << minFilterModes[minFilter].name << "_" << wrapModes[wrapMode].name;
3566 
3567                         if (tex3DSizes[size].name)
3568                             name << "_" << tex3DSizes[size].name;
3569 
3570                         coordTypeGroup->addChild(new TextureTestCase<Texture3DMipmapTestInstance>(
3571                             testCtx, name.str().c_str(), testParameters));
3572                     }
3573                 }
3574             }
3575 
3576             group3D->addChild(coordTypeGroup.release());
3577         }
3578 
3579         // 3D bias variants.
3580         {
3581             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3582             {
3583                 Texture3DMipmapTestCaseParameters testParameters;
3584                 testParameters.coordType  = COORDTYPE_BASIC_BIAS;
3585                 testParameters.minFilter  = minFilterModes[minFilter].mode;
3586                 testParameters.wrapR      = Sampler::REPEAT_GL;
3587                 testParameters.wrapS      = Sampler::REPEAT_GL;
3588                 testParameters.wrapT      = Sampler::REPEAT_GL;
3589                 testParameters.format     = VK_FORMAT_R8G8B8A8_UNORM;
3590                 testParameters.width      = tex3DSizes[0].width;
3591                 testParameters.height     = tex3DSizes[0].height;
3592                 testParameters.depth      = tex3DSizes[0].depth;
3593                 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3594                 testParameters.programs.push_back(PROGRAM_3D_FLOAT_BIAS);
3595 
3596                 biasGroup3D->addChild(new TextureTestCase<Texture3DMipmapTestInstance>(
3597                     testCtx, minFilterModes[minFilter].name, testParameters));
3598             }
3599         }
3600 
3601         // 3D LOD controls.
3602         {
3603             // MIN_LOD
3604             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3605             {
3606                 Texture3DMipmapTestCaseParameters testParameters;
3607                 testParameters.minFilter  = minFilterModes[minFilter].mode;
3608                 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3609                 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3610 
3611                 minLodGroup3D->addChild(new TextureTestCase<Texture3DMinLodTestInstance>(
3612                     testCtx, minFilterModes[minFilter].name, testParameters));
3613             }
3614 
3615             // MAX_LOD
3616             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3617             {
3618                 Texture3DMipmapTestCaseParameters testParameters;
3619                 testParameters.minFilter  = minFilterModes[minFilter].mode;
3620                 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3621                 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3622 
3623                 maxLodGroup3D->addChild(new TextureTestCase<Texture3DMaxLodTestInstance>(
3624                     testCtx, minFilterModes[minFilter].name, testParameters));
3625             }
3626         }
3627 
3628         {
3629             // BASE_LEVEL
3630             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3631             {
3632                 Texture3DMipmapTestCaseParameters testParameters;
3633                 testParameters.minFilter     = minFilterModes[minFilter].mode;
3634                 testParameters.minFilterName = minFilterModes[minFilter].name;
3635                 testParameters.aspectMask    = VK_IMAGE_ASPECT_COLOR_BIT;
3636                 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3637 
3638                 baseLevelGroup3D->addChild(new TextureTestCase<Texture3DBaseLevelTestInstance>(
3639                     testCtx, minFilterModes[minFilter].name, testParameters));
3640             }
3641 
3642             // MAX_LEVEL
3643             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3644             {
3645                 Texture3DMipmapTestCaseParameters testParameters;
3646                 testParameters.minFilter     = minFilterModes[minFilter].mode;
3647                 testParameters.minFilterName = minFilterModes[minFilter].name;
3648                 testParameters.aspectMask    = VK_IMAGE_ASPECT_COLOR_BIT;
3649                 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3650 
3651                 maxLevelGroup3D->addChild(new TextureTestCase<Texture3DMaxLevelTestInstance>(
3652                     testCtx, minFilterModes[minFilter].name, testParameters));
3653             }
3654         }
3655 
3656         // 3D VK_EXT_image_view_min_lod.
3657 #ifndef CTS_USES_VULKANSC
3658         {
3659             // MIN_LOD
3660             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3661             {
3662                 Texture3DMipmapTestCaseParameters testParameters;
3663                 testParameters.minFilter  = minFilterModes[minFilter].mode;
3664                 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
3665                 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3666                 testParameters.testType = util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3667 
3668                 imageViewMinLodGroup3D->addChild(new TextureTestCase<Texture3DImageViewMinLodTestInstance>(
3669                     testCtx, minFilterModes[minFilter].name, testParameters));
3670 
3671                 std::ostringstream name;
3672                 name << minFilterModes[minFilter].name << "_integer_texel_coord";
3673                 testParameters.testType = util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD;
3674                 imageViewMinLodGroup3D->addChild(
3675                     new Texture3DImageViewMinLodIntTexCoordTest(testCtx, name.str().c_str(), testParameters));
3676             }
3677 
3678             // BASE_LEVEL
3679             for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
3680             {
3681                 Texture3DMipmapTestCaseParameters testParameters;
3682                 testParameters.minFilter     = minFilterModes[minFilter].mode;
3683                 testParameters.minFilterName = minFilterModes[minFilter].name;
3684                 testParameters.aspectMask    = VK_IMAGE_ASPECT_COLOR_BIT;
3685                 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
3686                 testParameters.testType = util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD;
3687 
3688                 imageViewMinLodBaseLevelGroup3D->addChild(
3689                     new TextureTestCase<Texture3DImageViewMinLodBaseLevelTestInstance>(
3690                         testCtx, minFilterModes[minFilter].name, testParameters));
3691 
3692                 std::ostringstream name;
3693                 name << minFilterModes[minFilter].name << "_integer_texel_coord";
3694                 testParameters.testType =
3695                     util::TextureCommonTestCaseParameters::TEST_IMAGE_VIEW_MINLOD_INT_TEX_COORD_BASELEVEL;
3696                 imageViewMinLodBaseLevelGroup3D->addChild(
3697                     new Texture3DImageViewMinLodIntTexCoordTest(testCtx, name.str().c_str(), testParameters));
3698             }
3699 
3700             imageViewMinLodExtGroup3D->addChild(imageViewMinLodGroup3D.release());
3701             imageViewMinLodExtGroup3D->addChild(imageViewMinLodBaseLevelGroup3D.release());
3702         }
3703 #endif // CTS_USES_VULKANSC
3704 
3705         group3D->addChild(biasGroup3D.release());
3706         group3D->addChild(minLodGroup3D.release());
3707         group3D->addChild(maxLodGroup3D.release());
3708         group3D->addChild(baseLevelGroup3D.release());
3709         group3D->addChild(maxLevelGroup3D.release());
3710 #ifndef CTS_USES_VULKANSC
3711         group3D->addChild(imageViewMinLodExtGroup3D.release());
3712 #endif // CTS_USES_VULKANSC
3713 
3714         textureMipmappingTests->addChild(group3D.release());
3715     }
3716 
3717 #ifndef CTS_USES_VULKANSC
3718     {
3719         // Test minLod with textureGather operations
3720         const auto minLodGatherGroup =
3721             createTestGroup(testCtx, "min_lod_gather", populateMinLodGatherGroup, destroyDeviceHelpers);
3722         textureMipmappingTests->addChild(minLodGatherGroup);
3723     }
3724 #endif // CTS_USES_VULKANSC
3725 }
3726 
createTextureMipmappingTests(tcu::TestContext & testCtx)3727 tcu::TestCaseGroup *createTextureMipmappingTests(tcu::TestContext &testCtx)
3728 {
3729     return createTestGroup(testCtx, "mipmap", populateTextureMipmappingTests);
3730 }
3731 
3732 } // namespace texture
3733 } // namespace vkt
3734