xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/texture/vktTextureFilteringTests.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 (c) 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 Texture filtering tests.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "tcuVectorUtil.hpp"
27 #include "tcuTexVerifierUtil.hpp"
28 #include "vkImageUtil.hpp"
29 #include "vkMemUtil.hpp"
30 #include "vkPrograms.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vktTestCase.hpp"
34 #include "vktTestCaseUtil.hpp"
35 #include "vktTestGroupUtil.hpp"
36 #include "vktTextureFilteringTests.hpp"
37 #include "vktTextureTestUtil.hpp"
38 #include <string>
39 #include <vector>
40 
41 using namespace vk;
42 
43 namespace vkt
44 {
45 namespace texture
46 {
47 namespace util
48 {
49 
50 template <>
checkTextureSupport(Context & context,const Texture2DTestCaseParameters & testParameters)51 void checkTextureSupport(Context &context, const Texture2DTestCaseParameters &testParameters)
52 {
53     if (testParameters.minFilter == tcu::Sampler::Sampler::CUBIC ||
54         testParameters.minFilter == tcu::Sampler::Sampler::CUBIC_MIPMAP_NEAREST ||
55         testParameters.minFilter == tcu::Sampler::Sampler::CUBIC_MIPMAP_LINEAR ||
56         testParameters.magFilter == tcu::Sampler::Sampler::CUBIC)
57     {
58         context.requireDeviceFunctionality("VK_EXT_filter_cubic");
59 
60         // check if image format supports cubic filtering
61         const vk::VkPhysicalDeviceImageViewImageFormatInfoEXT imageViewImageFormatInfo = {
62             VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_IMAGE_FORMAT_INFO_EXT, // VkStructureType    sType;
63             DE_NULL,                                                            // void*              pNext;
64             VK_IMAGE_VIEW_TYPE_2D                                               // VkImageViewType    imageViewType;
65         };
66 
67         const vk::VkPhysicalDeviceImageFormatInfo2 formatInfo = {
68             VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, // VkStructureType       sType;
69             &imageViewImageFormatInfo,                             // const void*           pNext;
70             testParameters.format,                                 // VkFormat              format;
71             VK_IMAGE_TYPE_2D,                                      // VkImageType           type;
72             VK_IMAGE_TILING_OPTIMAL,                               // VkImageTiling         tiling;
73             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
74                 VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags     usage;
75             0u                                   // VkImageCreateFlags    flags;
76         };
77 
78         vk::VkFilterCubicImageViewImageFormatPropertiesEXT cubicImageViewProperties = {
79             VK_STRUCTURE_TYPE_FILTER_CUBIC_IMAGE_VIEW_IMAGE_FORMAT_PROPERTIES_EXT, // VkStructureType sType;
80             DE_NULL,                                                               // void* pNext;
81             false,                                                                 // VkBool32 filterCubic;
82             false                                                                  // VkBool32 filterCubicMinmax;
83         };
84 
85         vk::VkImageFormatProperties2 formatProperties = {
86             VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, // VkStructureType sType;
87             &cubicImageViewProperties,                   // void* pNext;
88             vk::VkImageFormatProperties()                // VkImageFormatProperties imageFormatProperties;
89         };
90 
91         const vk::VkResult res = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties2(
92             context.getPhysicalDevice(), &formatInfo, &formatProperties);
93         if (res == vk::VK_ERROR_FORMAT_NOT_SUPPORTED)
94             TCU_THROW(NotSupportedError, "Image format not supported");
95         VK_CHECK(res);
96 
97         if (!cubicImageViewProperties.filterCubic)
98             TCU_THROW(NotSupportedError, "Image format does not support cubic filtering");
99 
100         VkFormatProperties formatProps;
101         context.getInstanceInterface().getPhysicalDeviceFormatProperties(context.getPhysicalDevice(),
102                                                                          testParameters.format, &formatProps);
103         if ((formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_EXT) == 0)
104             TCU_THROW(NotSupportedError, "Format properties do not support cubic filtering feature");
105     }
106 
107     if (testParameters.wrapS == tcu::Sampler::Sampler::MIRRORED_ONCE ||
108         testParameters.wrapT == tcu::Sampler::Sampler::MIRRORED_ONCE)
109         context.requireDeviceFunctionality("VK_KHR_sampler_mirror_clamp_to_edge");
110 
111 #ifndef CTS_USES_VULKANSC
112     if (testParameters.format == VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 &&
113         context.getRGBA10X6FormatsFeaturesEXT().formatRgba10x6WithoutYCbCrSampler == VK_FALSE)
114         TCU_THROW(NotSupportedError, "formatRgba10x6WithoutYCbCrSampler not supported");
115 #endif
116 }
117 
118 template <>
checkTextureSupport(Context & context,const TextureCubeTestCaseParameters & testParameters)119 void checkTextureSupport(Context &context, const TextureCubeTestCaseParameters &testParameters)
120 {
121     if (testParameters.wrapS == tcu::Sampler::Sampler::MIRRORED_ONCE ||
122         testParameters.wrapT == tcu::Sampler::Sampler::MIRRORED_ONCE)
123         context.requireDeviceFunctionality("VK_KHR_sampler_mirror_clamp_to_edge");
124 }
125 
126 template <>
checkTextureSupport(Context & context,const Texture2DArrayTestCaseParameters & testParameters)127 void checkTextureSupport(Context &context, const Texture2DArrayTestCaseParameters &testParameters)
128 {
129     if (testParameters.wrapS == tcu::Sampler::Sampler::MIRRORED_ONCE ||
130         testParameters.wrapT == tcu::Sampler::Sampler::MIRRORED_ONCE)
131         context.requireDeviceFunctionality("VK_KHR_sampler_mirror_clamp_to_edge");
132 
133 #ifndef CTS_USES_VULKANSC
134     bool mipmaps =
135         (deLog2Floor32(de::max(testParameters.width, testParameters.height)) + 1) > 1 || testParameters.mipmaps;
136     if (testParameters.format == VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 && mipmaps &&
137         context.getRGBA10X6FormatsFeaturesEXT().formatRgba10x6WithoutYCbCrSampler == VK_FALSE)
138         TCU_THROW(NotSupportedError, "formatRgba10x6WithoutYCbCrSampler not supported");
139 #endif
140 }
141 
142 template <>
checkTextureSupport(Context & context,const Texture3DTestCaseParameters & testParameters)143 void checkTextureSupport(Context &context, const Texture3DTestCaseParameters &testParameters)
144 {
145     if (testParameters.wrapS == tcu::Sampler::Sampler::MIRRORED_ONCE ||
146         testParameters.wrapT == tcu::Sampler::Sampler::MIRRORED_ONCE ||
147         testParameters.wrapR == tcu::Sampler::Sampler::MIRRORED_ONCE)
148         context.requireDeviceFunctionality("VK_KHR_sampler_mirror_clamp_to_edge");
149 
150 #ifndef CTS_USES_VULKANSC
151     if (testParameters.format == VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 &&
152         context.getRGBA10X6FormatsFeaturesEXT().formatRgba10x6WithoutYCbCrSampler == VK_FALSE)
153         TCU_THROW(NotSupportedError, "formatRgba10x6WithoutYCbCrSampler not supported");
154 #endif
155 }
156 
157 template <>
checkTextureSupport(Context & context,const TextureCubeFilteringTestCaseParameters & testParameters)158 void checkTextureSupport(Context &context, const TextureCubeFilteringTestCaseParameters &testParameters)
159 {
160 #ifndef CTS_USES_VULKANSC
161     if (testParameters.format == VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16 &&
162         context.getRGBA10X6FormatsFeaturesEXT().formatRgba10x6WithoutYCbCrSampler == VK_FALSE)
163         TCU_THROW(NotSupportedError, "formatRgba10x6WithoutYCbCrSampler not supported");
164 #else
165     DE_UNREF(context);
166     DE_UNREF(testParameters);
167 #endif
168 }
169 
170 } // namespace util
171 
172 namespace
173 {
174 
175 using std::string;
176 using std::vector;
177 using tcu::Sampler;
178 using tcu::TestLog;
179 
180 using namespace texture::util;
181 using namespace glu::TextureTestUtil;
182 
183 enum
184 {
185     TEXCUBE_VIEWPORT_SIZE = 28,
186 
187     TEX2D_VIEWPORT_WIDTH  = 64,
188     TEX2D_VIEWPORT_HEIGHT = 64,
189 
190     TEX3D_VIEWPORT_WIDTH  = 64,
191     TEX3D_VIEWPORT_HEIGHT = 64,
192 };
193 
194 class Texture2DFilteringTestInstance : public TestInstance
195 {
196 public:
197     typedef Texture2DTestCaseParameters ParameterType;
198 
199     Texture2DFilteringTestInstance(Context &context, const ParameterType &testParameters);
200     ~Texture2DFilteringTestInstance(void);
201 
202     virtual tcu::TestStatus iterate(void);
203 
204 private:
205     Texture2DFilteringTestInstance(const Texture2DFilteringTestInstance &other);
206     Texture2DFilteringTestInstance &operator=(const Texture2DFilteringTestInstance &other);
207 
208     struct FilterCase
209     {
210         int textureIndex;
211 
212         tcu::Vec2 minCoord;
213         tcu::Vec2 maxCoord;
214 
FilterCasevkt::texture::__anon12a368720111::Texture2DFilteringTestInstance::FilterCase215         FilterCase(void) : textureIndex(-1)
216         {
217         }
218 
FilterCasevkt::texture::__anon12a368720111::Texture2DFilteringTestInstance::FilterCase219         FilterCase(int tex_, const tcu::Vec2 &minCoord_, const tcu::Vec2 &maxCoord_)
220             : textureIndex(tex_)
221             , minCoord(minCoord_)
222             , maxCoord(maxCoord_)
223         {
224         }
225     };
226 
227     const ParameterType m_testParameters;
228     vector<TestTexture2DSp> m_textures;
229     vector<FilterCase> m_cases;
230     TextureRenderer m_renderer;
231     int m_caseNdx;
232 };
233 
Texture2DFilteringTestInstance(Context & context,const ParameterType & testParameters)234 Texture2DFilteringTestInstance::Texture2DFilteringTestInstance(Context &context, const ParameterType &testParameters)
235     : TestInstance(context)
236     , m_testParameters(testParameters)
237     , m_renderer(context, testParameters.sampleCount, TEX2D_VIEWPORT_WIDTH, TEX2D_VIEWPORT_HEIGHT)
238     , m_caseNdx(0)
239 {
240     const bool mipmaps  = m_testParameters.mipmaps;
241     const int numLevels = mipmaps ? deLog2Floor32(de::max(m_testParameters.width, m_testParameters.height)) + 1 : 1;
242     const tcu::TextureFormat texFormat   = vk::mapVkFormat(m_testParameters.format);
243     const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFormat);
244     tcu::Vec4 cBias, cScale;
245     if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
246     {
247         const tcu::TextureFormat texFormatStencil   = vk::mapVkFormat(VK_FORMAT_S8_UINT);
248         const tcu::TextureFormatInfo fmtInfoStencil = tcu::getTextureFormatInfo(texFormatStencil);
249         cBias                                       = fmtInfoStencil.valueMin;
250         cScale                                      = fmtInfoStencil.valueMax - fmtInfoStencil.valueMin;
251     }
252     else
253     {
254         cBias  = fmtInfo.valueMin;
255         cScale = fmtInfo.valueMax - fmtInfo.valueMin;
256     }
257 
258     // Create 2 textures.
259     m_textures.reserve(2);
260     for (int ndx = 0; ndx < 2; ndx++)
261         if (mipmaps)
262             m_textures.push_back(TestTexture2DSp(new pipeline::TestTexture2D(
263                 vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height)));
264         else
265             m_textures.push_back(TestTexture2DSp(new pipeline::TestTexture2D(
266                 vk::mapVkFormat(m_testParameters.format), m_testParameters.width, m_testParameters.height, 1)));
267 
268     // Fill first gradient texture.
269     for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
270     {
271         const tcu::Vec4 gMin = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
272         const tcu::Vec4 gMax = tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) * cScale + cBias;
273 
274         if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
275             tcu::fillWithComponentGradients(
276                 getEffectiveDepthStencilAccess(m_textures[0]->getLevel(levelNdx, 0), tcu::Sampler::MODE_STENCIL), gMin,
277                 gMax);
278         else
279             tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, 0), gMin, gMax);
280     }
281 
282     // Fill second with grid texture.
283     for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
284     {
285         const uint32_t step   = 0x00ffffff / numLevels;
286         const uint32_t rgb    = step * levelNdx;
287         const uint32_t colorA = 0xff000000 | rgb;
288         const uint32_t colorB = 0xff000000 | ~rgb;
289 
290         if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
291             tcu::fillWithGrid(
292                 getEffectiveDepthStencilAccess(m_textures[1]->getLevel(levelNdx, 0), tcu::Sampler::MODE_STENCIL), 4,
293                 tcu::RGBA(colorA).toVec() * cScale + cBias, tcu::RGBA(colorB).toVec() * cScale + cBias);
294         else
295             tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, 0), 4, tcu::RGBA(colorA).toVec() * cScale + cBias,
296                               tcu::RGBA(colorB).toVec() * cScale + cBias);
297     }
298 
299     // Upload.
300     for (vector<TestTexture2DSp>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
301     {
302         m_renderer.add2DTexture(*i, testParameters.aspectMask);
303     }
304 
305     // Compute cases.
306     {
307         const struct
308         {
309             const int texNdx;
310             const float lodX;
311             const float lodY;
312             const float oX;
313             const float oY;
314         } cases[] = {
315             {0, 1.6f, 2.9f, -1.0f, -2.7f},
316             {0, -2.0f, -1.35f, -0.2f, 0.7f},
317             {1, 0.14f, 0.275f, -1.5f, -1.1f},
318             {1, -0.92f, -2.64f, 0.4f, -0.1f},
319         };
320 
321         for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(cases); caseNdx++)
322         {
323             const int texNdx = de::clamp(cases[caseNdx].texNdx, 0, (int)m_textures.size() - 1);
324             const float lodX = cases[caseNdx].lodX;
325             const float lodY = cases[caseNdx].lodY;
326             const float oX   = cases[caseNdx].oX;
327             const float oY   = cases[caseNdx].oY;
328             const float sX   = deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) /
329                              float(m_textures[texNdx]->getTexture().getWidth());
330             const float sY = deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) /
331                              float(m_textures[texNdx]->getTexture().getHeight());
332 
333             m_cases.push_back(FilterCase(texNdx, tcu::Vec2(oX, oY), tcu::Vec2(oX + sX, oY + sY)));
334         }
335     }
336 }
337 
~Texture2DFilteringTestInstance(void)338 Texture2DFilteringTestInstance::~Texture2DFilteringTestInstance(void)
339 {
340 }
341 
iterate(void)342 tcu::TestStatus Texture2DFilteringTestInstance::iterate(void)
343 {
344     tcu::TestLog &log                      = m_context.getTestContext().getLog();
345     const pipeline::TestTexture2D &texture = m_renderer.get2DTexture(m_cases[m_caseNdx].textureIndex);
346     const tcu::TextureFormat texFmt        = texture.getTextureFormat();
347     const tcu::TextureFormatInfo fmtInfo   = tcu::getTextureFormatInfo(texFmt);
348     const FilterCase &curCase              = m_cases[m_caseNdx];
349     ReferenceParams refParams(TEXTURETYPE_2D);
350     tcu::Surface rendered(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
351     vector<float> texCoord;
352 
353     // Setup params for reference.
354 
355     refParams.sampler = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter,
356                                             m_testParameters.magFilter, !m_testParameters.unnormal);
357     if (texFmt.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
358     {
359         refParams.sampler.depthStencilMode = tcu::Sampler::MODE_STENCIL;
360         refParams.samplerType              = SAMPLERTYPE_UINT;
361     }
362     else
363         refParams.samplerType = getSamplerType(texFmt);
364     refParams.colorBias  = fmtInfo.lookupBias;
365     refParams.colorScale = fmtInfo.lookupScale;
366     refParams.unnormal   = m_testParameters.unnormal;
367 
368     // Compute texture coordinates.
369     log << TestLog::Message << "Texture coordinates: " << curCase.minCoord << " -> " << curCase.maxCoord
370         << TestLog::EndMessage;
371     computeQuadTexCoord2D(texCoord, curCase.minCoord, curCase.maxCoord);
372 
373     m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], refParams);
374 
375     {
376         const bool isNearestOnly =
377             m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
378         const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
379         const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
380         const tcu::IVec4 colorBits = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2),
381                                          tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
382         tcu::LodPrecision lodPrecision;
383         tcu::LookupPrecision lookupPrecision;
384 
385         lodPrecision.derivateBits      = 18;
386         lodPrecision.lodBits           = 6;
387         lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
388         lookupPrecision.coordBits      = tcu::IVec3(20, 20, 0);
389         lookupPrecision.uvwBits        = tcu::IVec3(7, 7, 0);
390         lookupPrecision.colorMask      = getCompareMask(pixelFormat);
391 
392 #ifdef CTS_USES_VULKANSC
393         if (m_context.getTestContext().getCommandLine().isSubProcess())
394 #endif // CTS_USES_VULKANSC
395         {
396             const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(),
397                                                            (tcu::Texture2DView)texture.getTexture(), &texCoord[0],
398                                                            refParams, lookupPrecision, lodPrecision, pixelFormat);
399 
400             if (!isHighQuality)
401             {
402                 // Evaluate against lower precision requirements.
403                 lodPrecision.lodBits    = 4;
404                 lookupPrecision.uvwBits = tcu::IVec3(4, 4, 0);
405 
406                 log << TestLog::Message
407                     << "Warning: Verification against high precision requirements failed, trying with lower "
408                        "requirements."
409                     << TestLog::EndMessage;
410 
411                 const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(),
412                                                       (tcu::Texture2DView)texture.getTexture(), &texCoord[0], refParams,
413                                                       lookupPrecision, lodPrecision, pixelFormat);
414 
415                 if (!isOk)
416                 {
417                     log << TestLog::Message
418                         << "ERROR: Verification against low precision requirements failed, failing test case."
419                         << TestLog::EndMessage;
420                     return tcu::TestStatus::fail("Image verification failed");
421                 }
422             }
423         }
424     }
425 
426     m_caseNdx += 1;
427     return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
428 }
429 
430 class TextureCubeFilteringTestInstance : public TestInstance
431 {
432 public:
433     typedef TextureCubeFilteringTestCaseParameters ParameterType;
434 
435     TextureCubeFilteringTestInstance(Context &context, const ParameterType &testParameters);
436     ~TextureCubeFilteringTestInstance(void);
437 
438     virtual tcu::TestStatus iterate(void);
439 
440 private:
441     TextureCubeFilteringTestInstance(const TextureCubeFilteringTestInstance &other);
442     TextureCubeFilteringTestInstance &operator=(const TextureCubeFilteringTestInstance &other);
443 
444     struct FilterCase
445     {
446         int textureIndex;
447         tcu::Vec2 bottomLeft;
448         tcu::Vec2 topRight;
449 
FilterCasevkt::texture::__anon12a368720111::TextureCubeFilteringTestInstance::FilterCase450         FilterCase(void) : textureIndex(-1)
451         {
452         }
453 
FilterCasevkt::texture::__anon12a368720111::TextureCubeFilteringTestInstance::FilterCase454         FilterCase(int tex_, const tcu::Vec2 &bottomLeft_, const tcu::Vec2 &topRight_)
455             : textureIndex(tex_)
456             , bottomLeft(bottomLeft_)
457             , topRight(topRight_)
458         {
459         }
460     };
461 
462     const ParameterType m_testParameters;
463     vector<TestTextureCubeSp> m_textures;
464     vector<FilterCase> m_cases;
465     TextureRenderer m_renderer;
466     int m_caseNdx;
467 };
468 
TextureCubeFilteringTestInstance(Context & context,const ParameterType & testParameters)469 TextureCubeFilteringTestInstance::TextureCubeFilteringTestInstance(Context &context,
470                                                                    const ParameterType &testParameters)
471     : TestInstance(context)
472     , m_testParameters(testParameters)
473     , m_renderer(context, testParameters.sampleCount, TEXCUBE_VIEWPORT_SIZE, TEXCUBE_VIEWPORT_SIZE)
474     , m_caseNdx(0)
475 {
476     const int numLevels                  = deLog2Floor32(m_testParameters.size) + 1;
477     const tcu::TextureFormat texFormat   = vk::mapVkFormat(m_testParameters.format);
478     const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFormat);
479     tcu::Vec4 cBias, cScale;
480     if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
481     {
482         const tcu::TextureFormat texFormatStencil   = vk::mapVkFormat(VK_FORMAT_S8_UINT);
483         const tcu::TextureFormatInfo fmtInfoStencil = tcu::getTextureFormatInfo(texFormatStencil);
484         cBias                                       = fmtInfoStencil.valueMin;
485         cScale                                      = fmtInfoStencil.valueMax - fmtInfoStencil.valueMin;
486     }
487     else
488     {
489         cBias  = fmtInfo.valueMin;
490         cScale = fmtInfo.valueMax - fmtInfo.valueMin;
491     }
492 
493     m_textures.reserve(2);
494     for (int ndx = 0; ndx < 2; ndx++)
495         m_textures.push_back(TestTextureCubeSp(
496             new pipeline::TestTextureCube(vk::mapVkFormat(m_testParameters.format), m_testParameters.size)));
497 
498     // Fill first with gradient texture.
499     static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] = {
500         {tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)}, // negative x
501         {tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)}, // positive x
502         {tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)}, // negative y
503         {tcu::Vec4(0.0f, 0.0f, 0.5f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)}, // positive y
504         {tcu::Vec4(0.0f, 0.0f, 0.0f, 0.5f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f)}, // negative z
505         {tcu::Vec4(0.5f, 0.5f, 0.5f, 1.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)}  // positive z
506     };
507 
508     for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
509     {
510         for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
511         {
512             if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
513                 tcu::fillWithComponentGradients(
514                     getEffectiveDepthStencilAccess(m_textures[0]->getLevel(levelNdx, face), tcu::Sampler::MODE_STENCIL),
515                     gradients[face][0] * cScale + cBias, gradients[face][1] * cScale + cBias);
516             else
517                 tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, face),
518                                                 gradients[face][0] * cScale + cBias,
519                                                 gradients[face][1] * cScale + cBias);
520         }
521     }
522 
523     // Fill second with grid texture.
524     for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
525     {
526         for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
527         {
528             const uint32_t step   = 0x00ffffff / (numLevels * tcu::CUBEFACE_LAST);
529             const uint32_t rgb    = step * levelNdx * face;
530             const uint32_t colorA = 0xff000000 | rgb;
531             const uint32_t colorB = 0xff000000 | ~rgb;
532 
533             tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, face), 4, tcu::RGBA(colorA).toVec() * cScale + cBias,
534                               tcu::RGBA(colorB).toVec() * cScale + cBias);
535 
536             if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
537                 tcu::fillWithGrid(
538                     getEffectiveDepthStencilAccess(m_textures[1]->getLevel(levelNdx, face), tcu::Sampler::MODE_STENCIL),
539                     4, tcu::RGBA(colorA).toVec() * cScale + cBias, tcu::RGBA(colorB).toVec() * cScale + cBias);
540             else
541                 tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, face), 4,
542                                   tcu::RGBA(colorA).toVec() * cScale + cBias,
543                                   tcu::RGBA(colorB).toVec() * cScale + cBias);
544         }
545     }
546 
547     // Upload.
548     for (vector<TestTextureCubeSp>::iterator i = m_textures.begin(); i != m_textures.end(); i++)
549     {
550         m_renderer.addCubeTexture(*i, testParameters.aspectMask);
551     }
552 
553     // Compute cases
554     {
555         const int tex0 = 0;
556         const int tex1 = m_textures.size() > 1 ? 1 : 0;
557 
558         if (m_testParameters.onlySampleFaceInterior)
559         {
560             m_cases.push_back(FilterCase(tex0, tcu::Vec2(-0.8f, -0.8f), tcu::Vec2(0.8f, 0.8f))); // minification
561             m_cases.push_back(FilterCase(tex0, tcu::Vec2(0.5f, 0.65f), tcu::Vec2(0.8f, 0.8f)));  // magnification
562             m_cases.push_back(FilterCase(tex1, tcu::Vec2(-0.8f, -0.8f), tcu::Vec2(0.8f, 0.8f))); // minification
563             m_cases.push_back(FilterCase(tex1, tcu::Vec2(0.2f, 0.2f), tcu::Vec2(0.6f, 0.5f)));   // magnification
564         }
565         else
566         {
567             m_cases.push_back(FilterCase(tex0, tcu::Vec2(-1.25f, -1.2f), tcu::Vec2(1.2f, 1.25f))); // minification
568 
569             m_cases.push_back(FilterCase(tex0, tcu::Vec2(0.8f, 0.8f), tcu::Vec2(1.25f, 1.20f)));   // magnification
570             m_cases.push_back(FilterCase(tex1, tcu::Vec2(-1.19f, -1.3f), tcu::Vec2(1.1f, 1.35f))); // minification
571             m_cases.push_back(FilterCase(tex1, tcu::Vec2(-1.2f, -1.1f), tcu::Vec2(-0.8f, -0.8f))); // magnification
572         }
573     }
574 }
575 
~TextureCubeFilteringTestInstance(void)576 TextureCubeFilteringTestInstance::~TextureCubeFilteringTestInstance(void)
577 {
578 }
579 
getFaceDesc(const tcu::CubeFace face)580 const char *getFaceDesc(const tcu::CubeFace face)
581 {
582     switch (face)
583     {
584     case tcu::CUBEFACE_NEGATIVE_X:
585         return "-X";
586     case tcu::CUBEFACE_POSITIVE_X:
587         return "+X";
588     case tcu::CUBEFACE_NEGATIVE_Y:
589         return "-Y";
590     case tcu::CUBEFACE_POSITIVE_Y:
591         return "+Y";
592     case tcu::CUBEFACE_NEGATIVE_Z:
593         return "-Z";
594     case tcu::CUBEFACE_POSITIVE_Z:
595         return "+Z";
596     default:
597         DE_ASSERT(false);
598         return DE_NULL;
599     }
600 }
601 
iterate(void)602 tcu::TestStatus TextureCubeFilteringTestInstance::iterate(void)
603 {
604     tcu::TestLog &log = m_context.getTestContext().getLog();
605 
606     const pipeline::TestTextureCube &texture = m_renderer.getCubeTexture(m_cases[m_caseNdx].textureIndex);
607     const tcu::TextureFormat texFmt          = texture.getTextureFormat();
608     const tcu::TextureFormatInfo fmtInfo     = tcu::getTextureFormatInfo(texFmt);
609     const FilterCase &curCase                = m_cases[m_caseNdx];
610     ReferenceParams refParams(TEXTURETYPE_CUBE);
611 
612     // Params for reference computation.
613     refParams.sampler = util::createSampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, m_testParameters.minFilter,
614                                             m_testParameters.magFilter);
615     if (texFmt.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
616     {
617         refParams.sampler.depthStencilMode = tcu::Sampler::MODE_STENCIL;
618         refParams.samplerType              = SAMPLERTYPE_UINT;
619     }
620     else
621         refParams.samplerType = getSamplerType(texFmt);
622     refParams.sampler.seamlessCubeMap = true;
623     refParams.lodMode                 = LODMODE_EXACT;
624     refParams.colorBias               = fmtInfo.lookupBias;
625     refParams.colorScale              = fmtInfo.lookupScale;
626 
627     log << TestLog::Message << "Coordinates: " << curCase.bottomLeft << " -> " << curCase.topRight
628         << TestLog::EndMessage;
629 
630     for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
631     {
632         const tcu::CubeFace face = tcu::CubeFace(faceNdx);
633         tcu::Surface rendered(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
634         vector<float> texCoord;
635 
636         computeQuadTexCoordCube(texCoord, face, curCase.bottomLeft, curCase.topRight);
637 
638         log << TestLog::Message << "Face " << getFaceDesc(face) << TestLog::EndMessage;
639 
640         // \todo Log texture coordinates.
641 
642         m_renderer.renderQuad(rendered, curCase.textureIndex, &texCoord[0], refParams);
643 
644         {
645             const bool isNearestOnly =
646                 m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
647             const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
648             const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2],
649                                                formatBitDepth[3]);
650             const tcu::IVec4 colorBits = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2),
651                                              tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
652             tcu::LodPrecision lodPrecision;
653             tcu::LookupPrecision lookupPrecision;
654 
655             lodPrecision.derivateBits      = 10;
656             lodPrecision.lodBits           = 5;
657             lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
658             lookupPrecision.coordBits      = tcu::IVec3(10, 10, 10);
659             lookupPrecision.uvwBits        = tcu::IVec3(6, 6, 0);
660             lookupPrecision.colorMask      = getCompareMask(pixelFormat);
661 
662 #ifdef CTS_USES_VULKANSC
663             if (m_context.getTestContext().getCommandLine().isSubProcess())
664 #endif // CTS_USES_VULKANSC
665             {
666                 const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(),
667                                                                (tcu::TextureCubeView)texture.getTexture(), &texCoord[0],
668                                                                refParams, lookupPrecision, lodPrecision, pixelFormat);
669 
670                 if (!isHighQuality)
671                 {
672                     // Evaluate against lower precision requirements.
673                     lodPrecision.lodBits    = 4;
674                     lookupPrecision.uvwBits = tcu::IVec3(4, 4, 0);
675 
676                     log << TestLog::Message
677                         << "Warning: Verification against high precision requirements failed, trying with lower "
678                            "requirements."
679                         << TestLog::EndMessage;
680 
681                     const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(),
682                                                           (tcu::TextureCubeView)texture.getTexture(), &texCoord[0],
683                                                           refParams, lookupPrecision, lodPrecision, pixelFormat);
684 
685                     if (!isOk)
686                     {
687                         log << TestLog::Message
688                             << "ERROR: Verification against low precision requirements failed, failing test case."
689                             << TestLog::EndMessage;
690                         return tcu::TestStatus::fail("Image verification failed");
691                     }
692                 }
693             }
694         }
695     }
696 
697     m_caseNdx += 1;
698     return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
699 }
700 
701 // 2D array filtering
702 
703 class Texture2DArrayFilteringTestInstance : public TestInstance
704 {
705 public:
706     typedef Texture2DArrayTestCaseParameters ParameterType;
707 
708     Texture2DArrayFilteringTestInstance(Context &context, const ParameterType &testParameters);
709     ~Texture2DArrayFilteringTestInstance(void);
710 
711     virtual tcu::TestStatus iterate(void);
712 
713 private:
714     Texture2DArrayFilteringTestInstance(const Texture2DArrayFilteringTestInstance &);
715     Texture2DArrayFilteringTestInstance &operator=(const Texture2DArrayFilteringTestInstance &);
716 
717     struct FilterCase
718     {
719         int textureIndex;
720         tcu::Vec2 lod;
721         tcu::Vec2 offset;
722         tcu::Vec2 layerRange;
723 
FilterCasevkt::texture::__anon12a368720111::Texture2DArrayFilteringTestInstance::FilterCase724         FilterCase(void) : textureIndex(-1)
725         {
726         }
727 
FilterCasevkt::texture::__anon12a368720111::Texture2DArrayFilteringTestInstance::FilterCase728         FilterCase(const int tex_, const tcu::Vec2 &lod_, const tcu::Vec2 &offset_, const tcu::Vec2 &layerRange_)
729             : textureIndex(tex_)
730             , lod(lod_)
731             , offset(offset_)
732             , layerRange(layerRange_)
733         {
734         }
735     };
736 
737     const ParameterType m_testParameters;
738     vector<TestTexture2DArraySp> m_textures;
739     vector<FilterCase> m_cases;
740     TextureRenderer m_renderer;
741     int m_caseNdx;
742 };
743 
Texture2DArrayFilteringTestInstance(Context & context,const ParameterType & testParameters)744 Texture2DArrayFilteringTestInstance::Texture2DArrayFilteringTestInstance(Context &context,
745                                                                          const ParameterType &testParameters)
746     : TestInstance(context)
747     , m_testParameters(testParameters)
748     , m_renderer(context, testParameters.sampleCount, TEX3D_VIEWPORT_WIDTH, TEX3D_VIEWPORT_HEIGHT)
749     , m_caseNdx(0)
750 {
751     const int numLevels                  = deLog2Floor32(de::max(m_testParameters.width, m_testParameters.height)) + 1;
752     const tcu::TextureFormat texFormat   = vk::mapVkFormat(m_testParameters.format);
753     const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFormat);
754     tcu::Vec4 cBias, cScale;
755     if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
756     {
757         const tcu::TextureFormat texFormatStencil   = vk::mapVkFormat(VK_FORMAT_S8_UINT);
758         const tcu::TextureFormatInfo fmtInfoStencil = tcu::getTextureFormatInfo(texFormatStencil);
759         cBias                                       = fmtInfoStencil.valueMin;
760         cScale                                      = fmtInfoStencil.valueMax - fmtInfoStencil.valueMin;
761     }
762     else
763     {
764         cBias  = fmtInfo.valueMin;
765         cScale = fmtInfo.valueMax - fmtInfo.valueMin;
766     }
767 
768     // Create textures.
769     m_textures.reserve(2);
770     for (int ndx = 0; ndx < 2; ndx++)
771         m_textures.push_back(TestTexture2DArraySp(
772             new pipeline::TestTexture2DArray(vk::mapVkFormat(m_testParameters.format), m_testParameters.width,
773                                              m_testParameters.height, m_testParameters.numLayers)));
774 
775     const tcu::IVec4 levelSwz[] = {
776         tcu::IVec4(0, 1, 2, 3),
777         tcu::IVec4(2, 1, 3, 0),
778         tcu::IVec4(3, 0, 1, 2),
779         tcu::IVec4(1, 3, 2, 0),
780     };
781 
782     // Fill first gradient texture (gradient direction varies between layers).
783     for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
784     {
785         for (int layerNdx = 0; layerNdx < m_testParameters.numLayers; layerNdx++)
786         {
787             const tcu::IVec4 swz = levelSwz[layerNdx % DE_LENGTH_OF_ARRAY(levelSwz)];
788             const tcu::Vec4 gMin =
789                 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f).swizzle(swz[0], swz[1], swz[2], swz[3]) * cScale + cBias;
790             const tcu::Vec4 gMax =
791                 tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f).swizzle(swz[0], swz[1], swz[2], swz[3]) * cScale + cBias;
792 
793             if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
794                 tcu::fillWithComponentGradients(
795                     getEffectiveDepthStencilAccess(m_textures[0]->getLevel(levelNdx, layerNdx),
796                                                    tcu::Sampler::MODE_STENCIL),
797                     gMin, gMax);
798             else
799                 tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, layerNdx), gMin, gMax);
800         }
801     }
802 
803     // Fill second with grid texture (each layer has unique colors).
804     for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
805     {
806         for (int layerNdx = 0; layerNdx < m_testParameters.numLayers; layerNdx++)
807         {
808             const uint32_t step   = 0x00ffffff / (numLevels * m_testParameters.numLayers - 1);
809             const uint32_t rgb    = step * (levelNdx + layerNdx * numLevels);
810             const uint32_t colorA = 0xff000000 | rgb;
811             const uint32_t colorB = 0xff000000 | ~rgb;
812 
813             if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
814                 tcu::fillWithGrid(getEffectiveDepthStencilAccess(m_textures[1]->getLevel(levelNdx, layerNdx),
815                                                                  tcu::Sampler::MODE_STENCIL),
816                                   4, tcu::RGBA(colorA).toVec() * cScale + cBias,
817                                   tcu::RGBA(colorB).toVec() * cScale + cBias);
818             else
819                 tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, layerNdx), 4,
820                                   tcu::RGBA(colorA).toVec() * cScale + cBias,
821                                   tcu::RGBA(colorB).toVec() * cScale + cBias);
822         }
823     }
824 
825     // Upload.
826     for (vector<TestTexture2DArraySp>::const_iterator i = m_textures.begin(); i != m_textures.end(); i++)
827     {
828         m_renderer.add2DArrayTexture(*i, testParameters.aspectMask);
829     }
830 
831     // Test cases
832     m_cases.push_back(FilterCase(0, tcu::Vec2(1.5f, 2.8f), tcu::Vec2(-1.0f, -2.7f),
833                                  tcu::Vec2(-0.5f, float(m_testParameters.numLayers) + 0.5f)));
834     m_cases.push_back(FilterCase(1, tcu::Vec2(0.2f, 0.175f), tcu::Vec2(-2.0f, -3.7f),
835                                  tcu::Vec2(-0.5f, float(m_testParameters.numLayers) + 0.5f)));
836     m_cases.push_back(FilterCase(1, tcu::Vec2(-0.8f, -2.3f), tcu::Vec2(0.2f, -0.1f),
837                                  tcu::Vec2(float(m_testParameters.numLayers) + 0.5f, -0.5f)));
838     m_cases.push_back(FilterCase(0, tcu::Vec2(-2.0f, -1.5f), tcu::Vec2(-0.1f, 0.9f), tcu::Vec2(1.50001f, 1.49999f)));
839 }
840 
~Texture2DArrayFilteringTestInstance(void)841 Texture2DArrayFilteringTestInstance::~Texture2DArrayFilteringTestInstance(void)
842 {
843 }
844 
iterate(void)845 tcu::TestStatus Texture2DArrayFilteringTestInstance::iterate(void)
846 {
847     tcu::TestLog &log = m_context.getTestContext().getLog();
848 
849     const FilterCase &curCase                   = m_cases[m_caseNdx];
850     const pipeline::TestTexture2DArray &texture = m_renderer.get2DArrayTexture(curCase.textureIndex);
851     const tcu::TextureFormat texFmt             = texture.getTextureFormat();
852     const tcu::TextureFormatInfo fmtInfo        = tcu::getTextureFormatInfo(texFmt);
853     ReferenceParams refParams(TEXTURETYPE_2D_ARRAY);
854     tcu::Surface rendered(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
855     tcu::Vec3 texCoord[4];
856     const float *const texCoordPtr = (const float *)&texCoord[0];
857 
858     // Params for reference computation.
859 
860     refParams.sampler = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.minFilter,
861                                             m_testParameters.magFilter);
862     if (texFmt.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
863     {
864         refParams.sampler.depthStencilMode = tcu::Sampler::MODE_STENCIL;
865         refParams.samplerType              = SAMPLERTYPE_UINT;
866     }
867     else
868         refParams.samplerType = getSamplerType(texFmt);
869     refParams.lodMode    = LODMODE_EXACT;
870     refParams.colorBias  = fmtInfo.lookupBias;
871     refParams.colorScale = fmtInfo.lookupScale;
872 
873     // Compute texture coordinates.
874     log << TestLog::Message << "Approximate lod per axis = " << curCase.lod << ", offset = " << curCase.offset
875         << TestLog::EndMessage;
876 
877     {
878         const float lodX = curCase.lod.x();
879         const float lodY = curCase.lod.y();
880         const float oX   = curCase.offset.x();
881         const float oY   = curCase.offset.y();
882         const float sX =
883             deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[0]->getTexture().getWidth());
884         const float sY =
885             deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[0]->getTexture().getHeight());
886         const float l0 = curCase.layerRange.x();
887         const float l1 = curCase.layerRange.y();
888 
889         texCoord[0] = tcu::Vec3(oX, oY, l0);
890         texCoord[1] = tcu::Vec3(oX, oY + sY, l0 * 0.5f + l1 * 0.5f);
891         texCoord[2] = tcu::Vec3(oX + sX, oY, l0 * 0.5f + l1 * 0.5f);
892         texCoord[3] = tcu::Vec3(oX + sX, oY + sY, l1);
893     }
894 
895     m_renderer.renderQuad(rendered, curCase.textureIndex, texCoordPtr, refParams);
896 
897     {
898 
899         const bool isNearestOnly =
900             m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
901         const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
902         const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
903         const tcu::IVec4 colorBits = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2),
904                                          tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
905         tcu::LodPrecision lodPrecision;
906         tcu::LookupPrecision lookupPrecision;
907 
908         lodPrecision.derivateBits      = 18;
909         lodPrecision.lodBits           = 6;
910         lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
911         lookupPrecision.coordBits      = tcu::IVec3(20, 20, 20);
912         lookupPrecision.uvwBits        = tcu::IVec3(7, 7, 0);
913         lookupPrecision.colorMask      = getCompareMask(pixelFormat);
914 
915 #ifdef CTS_USES_VULKANSC
916         if (m_context.getTestContext().getCommandLine().isSubProcess())
917 #endif // CTS_USES_VULKANSC
918         {
919             const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(),
920                                                            (tcu::Texture2DArrayView)texture.getTexture(), texCoordPtr,
921                                                            refParams, lookupPrecision, lodPrecision, pixelFormat);
922 
923             if (!isHighQuality)
924             {
925                 // Evaluate against lower precision requirements.
926                 lodPrecision.lodBits    = 4;
927                 lookupPrecision.uvwBits = tcu::IVec3(4, 4, 0);
928 
929                 log << TestLog::Message
930                     << "Warning: Verification against high precision requirements failed, trying with lower "
931                        "requirements."
932                     << TestLog::EndMessage;
933 
934                 const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(),
935                                                       (tcu::Texture2DArrayView)texture.getTexture(), texCoordPtr,
936                                                       refParams, lookupPrecision, lodPrecision, pixelFormat);
937 
938                 if (!isOk)
939                 {
940                     log << TestLog::Message
941                         << "ERROR: Verification against low precision requirements failed, failing test case."
942                         << TestLog::EndMessage;
943                     return tcu::TestStatus::fail("Image verification failed");
944                 }
945             }
946         }
947     }
948 
949     m_caseNdx += 1;
950     return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
951 }
952 
953 // 3D filtering
954 
955 class Texture3DFilteringTestInstance : public TestInstance
956 {
957 public:
958     typedef Texture3DTestCaseParameters ParameterType;
959 
960     Texture3DFilteringTestInstance(Context &context, const ParameterType &testParameters);
961     ~Texture3DFilteringTestInstance(void);
962 
963     virtual tcu::TestStatus iterate(void);
964 
965 private:
966     Texture3DFilteringTestInstance(const Texture3DFilteringTestInstance &other);
967     Texture3DFilteringTestInstance &operator=(const Texture3DFilteringTestInstance &other);
968 
969     struct FilterCase
970     {
971         int textureIndex;
972         tcu::Vec3 lod;
973         tcu::Vec3 offset;
974 
FilterCasevkt::texture::__anon12a368720111::Texture3DFilteringTestInstance::FilterCase975         FilterCase(void) : textureIndex(-1)
976         {
977         }
978 
FilterCasevkt::texture::__anon12a368720111::Texture3DFilteringTestInstance::FilterCase979         FilterCase(const int tex_, const tcu::Vec3 &lod_, const tcu::Vec3 &offset_)
980             : textureIndex(tex_)
981             , lod(lod_)
982             , offset(offset_)
983         {
984         }
985     };
986 
987     const ParameterType m_testParameters;
988     vector<TestTexture3DSp> m_textures;
989     vector<FilterCase> m_cases;
990     TextureRenderer m_renderer;
991     int m_caseNdx;
992 };
993 
Texture3DFilteringTestInstance(Context & context,const ParameterType & testParameters)994 Texture3DFilteringTestInstance::Texture3DFilteringTestInstance(Context &context, const ParameterType &testParameters)
995     : TestInstance(context)
996     , m_testParameters(testParameters)
997     , m_renderer(context, testParameters.sampleCount, TEX3D_VIEWPORT_WIDTH, TEX3D_VIEWPORT_HEIGHT)
998     , m_caseNdx(0)
999 {
1000     const int numLevels =
1001         deLog2Floor32(de::max(de::max(m_testParameters.width, m_testParameters.height), m_testParameters.depth)) + 1;
1002     const tcu::TextureFormat texFormat   = vk::mapVkFormat(m_testParameters.format);
1003     const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFormat);
1004     tcu::Vec4 cBias, cScale;
1005     if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
1006     {
1007         const tcu::TextureFormat texFormatStencil   = vk::mapVkFormat(VK_FORMAT_S8_UINT);
1008         const tcu::TextureFormatInfo fmtInfoStencil = tcu::getTextureFormatInfo(texFormatStencil);
1009         cBias                                       = fmtInfoStencil.valueMin;
1010         cScale                                      = fmtInfoStencil.valueMax - fmtInfoStencil.valueMin;
1011     }
1012     else
1013     {
1014         cBias  = fmtInfo.valueMin;
1015         cScale = fmtInfo.valueMax - fmtInfo.valueMin;
1016     }
1017 
1018     // Create textures.
1019     m_textures.reserve(2);
1020     for (int ndx = 0; ndx < 2; ndx++)
1021         m_textures.push_back(TestTexture3DSp(
1022             new pipeline::TestTexture3D(vk::mapVkFormat(m_testParameters.format), m_testParameters.width,
1023                                         m_testParameters.height, m_testParameters.depth)));
1024 
1025     // Fill first gradient texture.
1026     for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1027     {
1028         const tcu::Vec4 gMin = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
1029         const tcu::Vec4 gMax = tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) * cScale + cBias;
1030 
1031         if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
1032             tcu::fillWithComponentGradients(
1033                 getEffectiveDepthStencilAccess(m_textures[0]->getLevel(levelNdx, 0), tcu::Sampler::MODE_STENCIL), gMin,
1034                 gMax);
1035         else
1036             tcu::fillWithComponentGradients(m_textures[0]->getLevel(levelNdx, 0), gMin, gMax);
1037     }
1038 
1039     // Fill second with grid texture.
1040     for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1041     {
1042         const uint32_t step   = 0x00ffffff / numLevels;
1043         const uint32_t rgb    = step * levelNdx;
1044         const uint32_t colorA = 0xff000000 | rgb;
1045         const uint32_t colorB = 0xff000000 | ~rgb;
1046 
1047         if (texFormat.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
1048             tcu::fillWithGrid(
1049                 getEffectiveDepthStencilAccess(m_textures[1]->getLevel(levelNdx, 0), tcu::Sampler::MODE_STENCIL), 4,
1050                 tcu::RGBA(colorA).toVec() * cScale + cBias, tcu::RGBA(colorB).toVec() * cScale + cBias);
1051         else
1052             tcu::fillWithGrid(m_textures[1]->getLevel(levelNdx, 0), 4, tcu::RGBA(colorA).toVec() * cScale + cBias,
1053                               tcu::RGBA(colorB).toVec() * cScale + cBias);
1054     }
1055 
1056     // Upload.
1057     for (vector<TestTexture3DSp>::const_iterator i = m_textures.begin(); i != m_textures.end(); i++)
1058     {
1059         m_renderer.add3DTexture(*i, testParameters.aspectMask);
1060     }
1061 
1062     // Test cases
1063     m_cases.push_back(FilterCase(0, tcu::Vec3(1.5f, 2.8f, 1.0f), tcu::Vec3(-1.0f, -2.7f, -2.275f)));
1064     m_cases.push_back(FilterCase(0, tcu::Vec3(-2.0f, -1.5f, -1.8f), tcu::Vec3(-0.1f, 0.9f, -0.25f)));
1065     m_cases.push_back(FilterCase(1, tcu::Vec3(0.2f, 0.175f, 0.3f), tcu::Vec3(-2.0f, -3.7f, -1.825f)));
1066     m_cases.push_back(FilterCase(1, tcu::Vec3(-0.8f, -2.3f, -2.5f), tcu::Vec3(0.2f, -0.1f, 1.325f)));
1067 }
1068 
~Texture3DFilteringTestInstance(void)1069 Texture3DFilteringTestInstance::~Texture3DFilteringTestInstance(void)
1070 {
1071 }
1072 
iterate(void)1073 tcu::TestStatus Texture3DFilteringTestInstance::iterate(void)
1074 {
1075     tcu::TestLog &log = m_context.getTestContext().getLog();
1076 
1077     const pipeline::TestTexture3D &texture = m_renderer.get3DTexture(m_cases[m_caseNdx].textureIndex);
1078     const tcu::TextureFormat texFmt        = texture.getTextureFormat();
1079     const tcu::TextureFormatInfo fmtInfo   = tcu::getTextureFormatInfo(texFmt);
1080     const FilterCase &curCase              = m_cases[m_caseNdx];
1081     ReferenceParams refParams(TEXTURETYPE_3D);
1082     tcu::Surface rendered(m_renderer.getRenderWidth(), m_renderer.getRenderHeight());
1083     tcu::Vec3 texCoord[4];
1084     const float *const texCoordPtr = (const float *)&texCoord[0];
1085 
1086     // Params for reference computation.
1087     refParams.sampler = util::createSampler(m_testParameters.wrapS, m_testParameters.wrapT, m_testParameters.wrapR,
1088                                             m_testParameters.minFilter, m_testParameters.magFilter);
1089     if (texFmt.order == tcu::TextureFormat::DS && m_testParameters.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)
1090     {
1091         refParams.sampler.depthStencilMode = tcu::Sampler::MODE_STENCIL;
1092         refParams.samplerType              = SAMPLERTYPE_UINT;
1093     }
1094     else
1095         refParams.samplerType = getSamplerType(texFmt);
1096     refParams.lodMode    = LODMODE_EXACT;
1097     refParams.colorBias  = fmtInfo.lookupBias;
1098     refParams.colorScale = fmtInfo.lookupScale;
1099 
1100     // Compute texture coordinates.
1101     log << TestLog::Message << "Approximate lod per axis = " << curCase.lod << ", offset = " << curCase.offset
1102         << TestLog::EndMessage;
1103 
1104     {
1105         const float lodX = curCase.lod.x();
1106         const float lodY = curCase.lod.y();
1107         const float lodZ = curCase.lod.z();
1108         const float oX   = curCase.offset.x();
1109         const float oY   = curCase.offset.y();
1110         const float oZ   = curCase.offset.z();
1111         const float sX =
1112             deFloatExp2(lodX) * float(m_renderer.getRenderWidth()) / float(m_textures[0]->getTexture().getWidth());
1113         const float sY =
1114             deFloatExp2(lodY) * float(m_renderer.getRenderHeight()) / float(m_textures[0]->getTexture().getHeight());
1115         const float sZ = deFloatExp2(lodZ) * float(de::max(m_renderer.getRenderWidth(), m_renderer.getRenderHeight())) /
1116                          float(m_textures[0]->getTexture().getDepth());
1117 
1118         texCoord[0] = tcu::Vec3(oX, oY, oZ);
1119         texCoord[1] = tcu::Vec3(oX, oY + sY, oZ + sZ * 0.5f);
1120         texCoord[2] = tcu::Vec3(oX + sX, oY, oZ + sZ * 0.5f);
1121         texCoord[3] = tcu::Vec3(oX + sX, oY + sY, oZ + sZ);
1122     }
1123 
1124     m_renderer.renderQuad(rendered, curCase.textureIndex, texCoordPtr, refParams);
1125 
1126     {
1127         const bool isNearestOnly =
1128             m_testParameters.minFilter == Sampler::NEAREST && m_testParameters.magFilter == Sampler::NEAREST;
1129         const tcu::IVec4 formatBitDepth = getTextureFormatBitDepth(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM));
1130         const tcu::PixelFormat pixelFormat(formatBitDepth[0], formatBitDepth[1], formatBitDepth[2], formatBitDepth[3]);
1131         const tcu::IVec4 colorBits = max(getBitsVec(pixelFormat) - (isNearestOnly ? 1 : 2),
1132                                          tcu::IVec4(0)); // 1 inaccurate bit if nearest only, 2 otherwise
1133         tcu::LodPrecision lodPrecision;
1134         tcu::LookupPrecision lookupPrecision;
1135 
1136         lodPrecision.derivateBits      = 18;
1137         lodPrecision.lodBits           = 6;
1138         lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale;
1139         lookupPrecision.coordBits      = tcu::IVec3(20, 20, 20);
1140         lookupPrecision.uvwBits        = tcu::IVec3(7, 7, 7);
1141         lookupPrecision.colorMask      = getCompareMask(pixelFormat);
1142 
1143 #ifdef CTS_USES_VULKANSC
1144         if (m_context.getTestContext().getCommandLine().isSubProcess())
1145 #endif // CTS_USES_VULKANSC
1146         {
1147             const bool isHighQuality = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(),
1148                                                            (tcu::Texture3DView)texture.getTexture(), texCoordPtr,
1149                                                            refParams, lookupPrecision, lodPrecision, pixelFormat);
1150 
1151             if (!isHighQuality)
1152             {
1153                 // Evaluate against lower precision requirements.
1154                 lodPrecision.lodBits    = 4;
1155                 lookupPrecision.uvwBits = tcu::IVec3(4, 4, 4);
1156 
1157                 log << TestLog::Message
1158                     << "Warning: Verification against high precision requirements failed, trying with lower "
1159                        "requirements."
1160                     << TestLog::EndMessage;
1161 
1162                 const bool isOk = verifyTextureResult(m_context.getTestContext(), rendered.getAccess(),
1163                                                       (tcu::Texture3DView)texture.getTexture(), texCoordPtr, refParams,
1164                                                       lookupPrecision, lodPrecision, pixelFormat);
1165 
1166                 if (!isOk)
1167                 {
1168                     log << TestLog::Message
1169                         << "ERROR: Verification against low precision requirements failed, failing test case."
1170                         << TestLog::EndMessage;
1171                     return tcu::TestStatus::fail("Image verification failed");
1172                 }
1173             }
1174         }
1175     }
1176 
1177     m_caseNdx += 1;
1178     return m_caseNdx < (int)m_cases.size() ? tcu::TestStatus::incomplete() : tcu::TestStatus::pass("Pass");
1179 }
1180 
verifierCanBeUsed(const VkFormat format,const Sampler::FilterMode minFilter,const Sampler::FilterMode magFilter)1181 bool verifierCanBeUsed(const VkFormat format, const Sampler::FilterMode minFilter, const Sampler::FilterMode magFilter)
1182 {
1183     const tcu::TextureFormat textureFormat             = mapVkFormat(format);
1184     const tcu::TextureChannelClass textureChannelClass = tcu::getTextureChannelClass(textureFormat.type);
1185 
1186     return !(!(textureChannelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT ||
1187                textureChannelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ||
1188                textureChannelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT) &&
1189              (tcu::TexVerifierUtil::isLinearFilter(minFilter) || tcu::TexVerifierUtil::isLinearFilter(magFilter) ||
1190               tcu::TexVerifierUtil::isCubicFilter(minFilter) || tcu::TexVerifierUtil::isCubicFilter(magFilter)));
1191 }
1192 
1193 } // namespace
1194 
populateTextureFilteringTests(tcu::TestCaseGroup * textureFilteringTests)1195 void populateTextureFilteringTests(tcu::TestCaseGroup *textureFilteringTests)
1196 {
1197     tcu::TestContext &testCtx = textureFilteringTests->getTestContext();
1198 
1199     static const struct
1200     {
1201         const char *const name;
1202         const Sampler::WrapMode mode;
1203     } wrapModes[] = {{"repeat", Sampler::REPEAT_GL},
1204                      {"mirrored_repeat", Sampler::MIRRORED_REPEAT_GL},
1205                      {"clamp_to_edge", Sampler::CLAMP_TO_EDGE},
1206                      {"clamp_to_border", Sampler::CLAMP_TO_BORDER},
1207                      {"mirror_clamp_to_edge", Sampler::MIRRORED_ONCE}};
1208 
1209     struct FilterModes
1210     {
1211         const char *const name;
1212         const Sampler::FilterMode mode;
1213     };
1214 
1215     static const FilterModes minFilterModes[] = {{"nearest", Sampler::NEAREST},
1216                                                  {"linear", Sampler::LINEAR},
1217                                                  {"nearest_mipmap_nearest", Sampler::NEAREST_MIPMAP_NEAREST},
1218                                                  {"linear_mipmap_nearest", Sampler::LINEAR_MIPMAP_NEAREST},
1219                                                  {"nearest_mipmap_linear", Sampler::NEAREST_MIPMAP_LINEAR},
1220                                                  {"linear_mipmap_linear", Sampler::LINEAR_MIPMAP_LINEAR}};
1221 
1222     static const FilterModes magFilterModes[] = {{"nearest", Sampler::NEAREST}, {"linear", Sampler::LINEAR}};
1223 
1224     static const FilterModes minFilterModes2D[] = {{"nearest", Sampler::NEAREST},
1225                                                    {"linear", Sampler::LINEAR},
1226                                                    {"cubic", Sampler::CUBIC},
1227                                                    {"nearest_mipmap_nearest", Sampler::NEAREST_MIPMAP_NEAREST},
1228                                                    {"linear_mipmap_nearest", Sampler::LINEAR_MIPMAP_NEAREST},
1229                                                    {"nearest_mipmap_linear", Sampler::NEAREST_MIPMAP_LINEAR},
1230                                                    {"linear_mipmap_linear", Sampler::LINEAR_MIPMAP_LINEAR},
1231                                                    {"cubic_mipmap_nearest", Sampler::CUBIC_MIPMAP_NEAREST},
1232                                                    {"cubic_mipmap_linear", Sampler::CUBIC_MIPMAP_LINEAR}};
1233 
1234     static const FilterModes magFilterModes2D[] = {
1235         {"nearest", Sampler::NEAREST}, {"linear", Sampler::LINEAR}, {"cubic", Sampler::CUBIC}};
1236 
1237     static const struct
1238     {
1239         const int width;
1240         const int height;
1241     } sizes2D[] = {{4, 8}, {32, 64}, {128, 128}, {3, 7}, {31, 55}, {127, 99}};
1242 
1243     static const struct
1244     {
1245         const int size;
1246     } sizesCube[] = {{8}, {64}, {128}, {7}, {63}};
1247 
1248     static const struct
1249     {
1250         const int width;
1251         const int height;
1252         const int numLayers;
1253     } sizes2DArray[] = {{4, 8, 8}, {32, 64, 16}, {128, 32, 64}, {3, 7, 5}, {63, 63, 63}};
1254 
1255     static const struct
1256     {
1257         const int width;
1258         const int height;
1259         const int depth;
1260     } sizes3D[] = {{4, 8, 8}, {32, 64, 16}, {128, 32, 64}, {3, 7, 5}, {63, 63, 63}};
1261 
1262     static const struct
1263     {
1264         const char *const name;
1265         const VkFormat format;
1266         const VkImageAspectFlags aspectMask;
1267         const Program program2D;
1268         const Program programCube;
1269         const Program program2DArray;
1270         const Program program3D;
1271     } filterableFormatsByType[] = {
1272         {"r16g16b16a16_sfloat", VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1273          PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1274         {"b10g11r11_ufloat", VK_FORMAT_B10G11R11_UFLOAT_PACK32, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1275          PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1276         {"e5b9g9r9_ufloat", VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1277          PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1278         {"r8g8b8a8_unorm", VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT, PROGRAM_CUBE_FLOAT,
1279          PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1280         {"r8g8b8a8_snorm", VK_FORMAT_R8G8B8A8_SNORM, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT, PROGRAM_CUBE_FLOAT,
1281          PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1282         {"r5g6b5_unorm", VK_FORMAT_R5G6B5_UNORM_PACK16, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT, PROGRAM_CUBE_FLOAT,
1283          PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1284         {"r10x6g10x6b10x6a10x6_unorm", VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, VK_IMAGE_ASPECT_COLOR_BIT,
1285          PROGRAM_2D_FLOAT, PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1286         {"r4g4b4a4_unorm", VK_FORMAT_R4G4B4A4_UNORM_PACK16, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1287          PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1288         {"a4r4g4b4_unorm", VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1289          PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1290         {"a4b4g4r4_unorm", VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1291          PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1292         {"r5g5b5a1_unorm", VK_FORMAT_R5G5B5A1_UNORM_PACK16, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1293          PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1294         {"a8b8g8r8_srgb", VK_FORMAT_A8B8G8R8_SRGB_PACK32, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1295          PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1296         {"a1r5g5b5_unorm", VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_IMAGE_ASPECT_COLOR_BIT, PROGRAM_2D_FLOAT,
1297          PROGRAM_CUBE_FLOAT, PROGRAM_2D_ARRAY_FLOAT, PROGRAM_3D_FLOAT},
1298         {"s8_uint", VK_FORMAT_S8_UINT, VK_IMAGE_ASPECT_STENCIL_BIT, PROGRAM_2D_UINT, PROGRAM_CUBE_UINT,
1299          PROGRAM_2D_ARRAY_UINT, PROGRAM_3D_UINT},
1300         {"d24_unorm_s8_uint_stencil", VK_FORMAT_D24_UNORM_S8_UINT, VK_IMAGE_ASPECT_STENCIL_BIT, PROGRAM_2D_UINT,
1301          PROGRAM_CUBE_UINT, PROGRAM_2D_ARRAY_UINT, PROGRAM_3D_UINT},
1302         {"d32_sfloat_s8_uint_stencil", VK_FORMAT_D32_SFLOAT_S8_UINT, VK_IMAGE_ASPECT_STENCIL_BIT, PROGRAM_2D_UINT,
1303          PROGRAM_CUBE_UINT, PROGRAM_2D_ARRAY_UINT, PROGRAM_3D_UINT}};
1304 
1305     // 2D texture filtering.
1306     {
1307         // 2D Texture Filtering
1308         de::MovePtr<tcu::TestCaseGroup> group2D(new tcu::TestCaseGroup(testCtx, "2d"));
1309 
1310         // 2D Texture Formats
1311         de::MovePtr<tcu::TestCaseGroup> formatsGroup(new tcu::TestCaseGroup(testCtx, "formats"));
1312         de::MovePtr<tcu::TestCaseGroup> sizesGroup(new tcu::TestCaseGroup(testCtx, "sizes"));
1313         de::MovePtr<tcu::TestCaseGroup> combinationsGroup(new tcu::TestCaseGroup(testCtx, "combinations"));
1314 
1315         // Formats.
1316         for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1317         {
1318             const string filterGroupName = filterableFormatsByType[fmtNdx].name;
1319             de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1320 
1321             for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes2D); filterNdx++)
1322             {
1323                 const Sampler::FilterMode minFilter = minFilterModes2D[filterNdx].mode;
1324                 const bool isMipmap =
1325                     minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR && minFilter != Sampler::CUBIC;
1326                 const string name = minFilterModes2D[filterNdx].name;
1327                 Texture2DTestCaseParameters testParameters;
1328 
1329                 testParameters.format    = filterableFormatsByType[fmtNdx].format;
1330                 testParameters.minFilter = minFilter;
1331                 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1332                 testParameters.mipmaps   = true;
1333 
1334                 testParameters.wrapS  = Sampler::REPEAT_GL;
1335                 testParameters.wrapT  = Sampler::REPEAT_GL;
1336                 testParameters.width  = 64;
1337                 testParameters.height = 64;
1338 
1339                 testParameters.aspectMask = filterableFormatsByType[fmtNdx].aspectMask;
1340                 testParameters.programs.push_back(filterableFormatsByType[fmtNdx].program2D);
1341 
1342                 // Some combinations of the tests have to be skipped due to the restrictions of the verifiers.
1343                 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1344                 {
1345                     filterGroup->addChild(
1346                         new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1347                 }
1348             }
1349             formatsGroup->addChild(filterGroup.release());
1350         }
1351 
1352         // Sizes.
1353         for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2D); sizeNdx++)
1354         {
1355             const string filterGroupName =
1356                 de::toString(sizes2D[sizeNdx].width) + "x" + de::toString(sizes2D[sizeNdx].height);
1357             de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1358 
1359             for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes2D); filterNdx++)
1360             {
1361                 const Sampler::FilterMode minFilter = minFilterModes2D[filterNdx].mode;
1362                 const bool isMipmap =
1363                     minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR && minFilter != Sampler::CUBIC;
1364                 const string name = minFilterModes2D[filterNdx].name;
1365                 Texture2DTestCaseParameters testParameters;
1366 
1367                 testParameters.format    = VK_FORMAT_R8G8B8A8_UNORM;
1368                 testParameters.minFilter = minFilter;
1369                 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1370                 testParameters.mipmaps   = true;
1371 
1372                 testParameters.wrapS  = Sampler::REPEAT_GL;
1373                 testParameters.wrapT  = Sampler::REPEAT_GL;
1374                 testParameters.width  = sizes2D[sizeNdx].width;
1375                 testParameters.height = sizes2D[sizeNdx].height;
1376 
1377                 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1378                 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1379 
1380                 filterGroup->addChild(
1381                     new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1382             }
1383             sizesGroup->addChild(filterGroup.release());
1384         }
1385 
1386         // Wrap modes.
1387         for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes2D); minFilterNdx++)
1388         {
1389             de::MovePtr<tcu::TestCaseGroup> minFilterGroup(
1390                 new tcu::TestCaseGroup(testCtx, minFilterModes2D[minFilterNdx].name));
1391 
1392             for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes2D); magFilterNdx++)
1393             {
1394                 de::MovePtr<tcu::TestCaseGroup> magFilterGroup(
1395                     new tcu::TestCaseGroup(testCtx, magFilterModes2D[magFilterNdx].name));
1396 
1397                 for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1398                 {
1399                     de::MovePtr<tcu::TestCaseGroup> wrapSGroup(
1400                         new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name));
1401 
1402                     for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1403                     {
1404                         const string name = wrapModes[wrapTNdx].name;
1405                         Texture2DTestCaseParameters testParameters;
1406 
1407                         testParameters.format    = VK_FORMAT_R8G8B8A8_UNORM;
1408                         testParameters.minFilter = minFilterModes2D[minFilterNdx].mode;
1409                         testParameters.magFilter = magFilterModes2D[magFilterNdx].mode;
1410                         testParameters.mipmaps   = true;
1411 
1412                         testParameters.wrapS  = wrapModes[wrapSNdx].mode;
1413                         testParameters.wrapT  = wrapModes[wrapTNdx].mode;
1414                         testParameters.width  = 63;
1415                         testParameters.height = 57;
1416 
1417                         testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1418                         testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1419 
1420                         wrapSGroup->addChild(
1421                             new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1422                     }
1423                     magFilterGroup->addChild(wrapSGroup.release());
1424                 }
1425                 minFilterGroup->addChild(magFilterGroup.release());
1426             }
1427             combinationsGroup->addChild(minFilterGroup.release());
1428         }
1429 
1430         group2D->addChild(formatsGroup.release());
1431         group2D->addChild(sizesGroup.release());
1432         group2D->addChild(combinationsGroup.release());
1433 
1434         textureFilteringTests->addChild(group2D.release());
1435     }
1436 
1437     // Unnormalized texture filtering.
1438     {
1439         de::MovePtr<tcu::TestCaseGroup> groupUnnormal(new tcu::TestCaseGroup(testCtx, "unnormal"));
1440 
1441         de::MovePtr<tcu::TestCaseGroup> formatsGroup(new tcu::TestCaseGroup(testCtx, "formats"));
1442         de::MovePtr<tcu::TestCaseGroup> sizesGroup(new tcu::TestCaseGroup(testCtx, "sizes"));
1443 
1444         // Formats.
1445         for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1446         {
1447             const string filterGroupName = filterableFormatsByType[fmtNdx].name;
1448             de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1449 
1450             for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(magFilterModes2D); filterNdx++)
1451             {
1452                 const Sampler::FilterMode magFilter = magFilterModes2D[filterNdx].mode;
1453                 const string name                   = magFilterModes2D[filterNdx].name;
1454                 Texture2DTestCaseParameters testParameters;
1455 
1456                 testParameters.unnormal = true;
1457 
1458                 testParameters.format    = filterableFormatsByType[fmtNdx].format;
1459                 testParameters.minFilter = magFilter;
1460                 testParameters.magFilter = magFilter;
1461                 testParameters.mipmaps   = false;
1462 
1463                 testParameters.wrapS  = ((fmtNdx ^ filterNdx) & 1) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1464                 testParameters.wrapT  = ((fmtNdx ^ filterNdx) & 2) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1465                 testParameters.width  = 64;
1466                 testParameters.height = 64;
1467 
1468                 testParameters.aspectMask = filterableFormatsByType[fmtNdx].aspectMask;
1469                 testParameters.programs.push_back(filterableFormatsByType[fmtNdx].program2D);
1470 
1471                 // Some combinations of the tests have to be skipped due to the restrictions of the verifiers.
1472                 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1473                 {
1474                     filterGroup->addChild(
1475                         new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1476                 }
1477             }
1478             formatsGroup->addChild(filterGroup.release());
1479         }
1480 
1481         // Sizes.
1482         for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2D); sizeNdx++)
1483         {
1484             const string filterGroupName =
1485                 de::toString(sizes2D[sizeNdx].width) + "x" + de::toString(sizes2D[sizeNdx].height);
1486             de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1487 
1488             for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(magFilterModes2D); filterNdx++)
1489             {
1490                 const Sampler::FilterMode magFilter = magFilterModes2D[filterNdx].mode;
1491                 const string name                   = magFilterModes2D[filterNdx].name;
1492                 Texture2DTestCaseParameters testParameters;
1493 
1494                 testParameters.unnormal  = true;
1495                 testParameters.format    = VK_FORMAT_R8G8B8A8_UNORM;
1496                 testParameters.minFilter = magFilter;
1497                 testParameters.magFilter = magFilter;
1498                 testParameters.mipmaps   = false;
1499 
1500                 testParameters.wrapS  = ((sizeNdx ^ filterNdx) & 1) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1501                 testParameters.wrapT  = ((sizeNdx ^ filterNdx) & 2) ? Sampler::CLAMP_TO_EDGE : Sampler::CLAMP_TO_BORDER;
1502                 testParameters.width  = sizes2D[sizeNdx].width;
1503                 testParameters.height = sizes2D[sizeNdx].height;
1504 
1505                 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1506                 testParameters.programs.push_back(PROGRAM_2D_FLOAT);
1507 
1508                 filterGroup->addChild(
1509                     new TextureTestCase<Texture2DFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1510             }
1511             sizesGroup->addChild(filterGroup.release());
1512         }
1513 
1514         groupUnnormal->addChild(formatsGroup.release());
1515         groupUnnormal->addChild(sizesGroup.release());
1516 
1517         textureFilteringTests->addChild(groupUnnormal.release());
1518     }
1519 
1520     // Cube map texture filtering.
1521     {
1522         de::MovePtr<tcu::TestCaseGroup> groupCube(new tcu::TestCaseGroup(testCtx, "cube"));
1523 
1524         de::MovePtr<tcu::TestCaseGroup> formatsGroup(new tcu::TestCaseGroup(testCtx, "formats"));
1525         de::MovePtr<tcu::TestCaseGroup> sizesGroup(new tcu::TestCaseGroup(testCtx, "sizes"));
1526         de::MovePtr<tcu::TestCaseGroup> combinationsGroup(new tcu::TestCaseGroup(testCtx, "combinations"));
1527         de::MovePtr<tcu::TestCaseGroup> onlyFaceInteriorGroup(new tcu::TestCaseGroup(testCtx, "no_edges_visible"));
1528 
1529         // Formats.
1530         for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1531         {
1532             const string filterGroupName = filterableFormatsByType[fmtNdx].name;
1533             de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1534 
1535             for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1536             {
1537                 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1538                 const bool isMipmap                 = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1539                 const string name                   = minFilterModes[filterNdx].name;
1540                 TextureCubeFilteringTestCaseParameters testParameters;
1541 
1542                 testParameters.format    = filterableFormatsByType[fmtNdx].format;
1543                 testParameters.minFilter = minFilter;
1544                 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1545 
1546                 testParameters.wrapS                  = Sampler::REPEAT_GL;
1547                 testParameters.wrapT                  = Sampler::REPEAT_GL;
1548                 testParameters.onlySampleFaceInterior = false;
1549                 testParameters.size                   = 64;
1550 
1551                 testParameters.aspectMask = filterableFormatsByType[fmtNdx].aspectMask;
1552                 testParameters.programs.push_back(filterableFormatsByType[fmtNdx].programCube);
1553 
1554                 // Some tests have to be skipped due to the restrictions of the verifiers.
1555                 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1556                 {
1557                     filterGroup->addChild(
1558                         new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1559                 }
1560             }
1561             formatsGroup->addChild(filterGroup.release());
1562         }
1563 
1564         // Sizes.
1565         for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizesCube); sizeNdx++)
1566         {
1567             const string filterGroupName =
1568                 de::toString(sizesCube[sizeNdx].size) + "x" + de::toString(sizesCube[sizeNdx].size);
1569             de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1570 
1571             for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1572             {
1573                 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1574                 const bool isMipmap                 = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1575                 const string name                   = minFilterModes[filterNdx].name;
1576                 TextureCubeFilteringTestCaseParameters testParameters;
1577 
1578                 testParameters.format                 = VK_FORMAT_R8G8B8A8_UNORM;
1579                 testParameters.minFilter              = minFilter;
1580                 testParameters.magFilter              = isMipmap ? Sampler::LINEAR : minFilter;
1581                 testParameters.wrapS                  = Sampler::REPEAT_GL;
1582                 testParameters.wrapT                  = Sampler::REPEAT_GL;
1583                 testParameters.onlySampleFaceInterior = false;
1584                 testParameters.size                   = sizesCube[sizeNdx].size;
1585 
1586                 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1587                 testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1588 
1589                 filterGroup->addChild(
1590                     new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1591             }
1592             sizesGroup->addChild(filterGroup.release());
1593         }
1594 
1595         // Filter/wrap mode combinations.
1596         for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1597         {
1598             de::MovePtr<tcu::TestCaseGroup> minFilterGroup(
1599                 new tcu::TestCaseGroup(testCtx, minFilterModes[minFilterNdx].name));
1600 
1601             for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1602             {
1603                 de::MovePtr<tcu::TestCaseGroup> magFilterGroup(
1604                     new tcu::TestCaseGroup(testCtx, magFilterModes[magFilterNdx].name));
1605 
1606                 for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1607                 {
1608                     de::MovePtr<tcu::TestCaseGroup> wrapSGroup(
1609                         new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name));
1610 
1611                     for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1612                     {
1613                         const string name = wrapModes[wrapTNdx].name;
1614                         TextureCubeFilteringTestCaseParameters testParameters;
1615 
1616                         testParameters.format                 = VK_FORMAT_R8G8B8A8_UNORM;
1617                         testParameters.minFilter              = minFilterModes[minFilterNdx].mode;
1618                         testParameters.magFilter              = magFilterModes[magFilterNdx].mode;
1619                         testParameters.wrapS                  = wrapModes[wrapSNdx].mode;
1620                         testParameters.wrapT                  = wrapModes[wrapTNdx].mode;
1621                         testParameters.onlySampleFaceInterior = false;
1622                         testParameters.size                   = 63;
1623 
1624                         testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1625                         testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1626 
1627                         wrapSGroup->addChild(new TextureTestCase<TextureCubeFilteringTestInstance>(
1628                             testCtx, name.c_str(), testParameters));
1629                     }
1630                     magFilterGroup->addChild(wrapSGroup.release());
1631                 }
1632                 minFilterGroup->addChild(magFilterGroup.release());
1633             }
1634             combinationsGroup->addChild(minFilterGroup.release());
1635         }
1636 
1637         // Cases with no visible cube edges.
1638         for (int isLinearI = 0; isLinearI <= 1; isLinearI++)
1639         {
1640             const bool isLinear = isLinearI != 0;
1641             const string name   = isLinear ? "linear" : "nearest";
1642             TextureCubeFilteringTestCaseParameters testParameters;
1643 
1644             testParameters.format                 = VK_FORMAT_R8G8B8A8_UNORM;
1645             testParameters.minFilter              = isLinear ? Sampler::LINEAR : Sampler::NEAREST;
1646             testParameters.magFilter              = isLinear ? Sampler::LINEAR : Sampler::NEAREST;
1647             testParameters.wrapS                  = Sampler::REPEAT_GL;
1648             testParameters.wrapT                  = Sampler::REPEAT_GL;
1649             testParameters.onlySampleFaceInterior = true;
1650             testParameters.size                   = 63;
1651 
1652             testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1653             testParameters.programs.push_back(PROGRAM_CUBE_FLOAT);
1654 
1655             onlyFaceInteriorGroup->addChild(
1656                 new TextureTestCase<TextureCubeFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1657         }
1658 
1659         groupCube->addChild(formatsGroup.release());
1660         groupCube->addChild(sizesGroup.release());
1661         groupCube->addChild(combinationsGroup.release());
1662         groupCube->addChild(onlyFaceInteriorGroup.release());
1663 
1664         textureFilteringTests->addChild(groupCube.release());
1665     }
1666 
1667     // 2D array texture filtering.
1668     {
1669         de::MovePtr<tcu::TestCaseGroup> group2DArray(new tcu::TestCaseGroup(testCtx, "2d_array"));
1670 
1671         de::MovePtr<tcu::TestCaseGroup> formatsGroup(new tcu::TestCaseGroup(testCtx, "formats"));
1672         de::MovePtr<tcu::TestCaseGroup> sizesGroup(new tcu::TestCaseGroup(testCtx, "sizes"));
1673         de::MovePtr<tcu::TestCaseGroup> combinationsGroup(new tcu::TestCaseGroup(testCtx, "combinations"));
1674 
1675         // Formats.
1676         for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1677         {
1678             const string filterGroupName = filterableFormatsByType[fmtNdx].name;
1679             de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1680 
1681             for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1682             {
1683                 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1684                 const char *const filterName        = minFilterModes[filterNdx].name;
1685                 const bool isMipmap                 = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1686                 const char *const formatName        = filterableFormatsByType[fmtNdx].name;
1687                 const string name                   = string(formatName) + "_" + filterName;
1688                 Texture2DArrayTestCaseParameters testParameters;
1689 
1690                 testParameters.format    = filterableFormatsByType[fmtNdx].format;
1691                 testParameters.minFilter = minFilter;
1692                 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1693 
1694                 testParameters.wrapS     = Sampler::REPEAT_GL;
1695                 testParameters.wrapT     = Sampler::REPEAT_GL;
1696                 testParameters.width     = 128;
1697                 testParameters.height    = 128;
1698                 testParameters.numLayers = 8;
1699 
1700                 testParameters.aspectMask = filterableFormatsByType[fmtNdx].aspectMask;
1701                 testParameters.programs.push_back(filterableFormatsByType[fmtNdx].program2DArray);
1702 
1703                 // Some tests have to be skipped due to the restrictions of the verifiers.
1704                 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1705                 {
1706                     filterGroup->addChild(new TextureTestCase<Texture2DArrayFilteringTestInstance>(
1707                         testCtx, name.c_str(), testParameters));
1708                 }
1709             }
1710             formatsGroup->addChild(filterGroup.release());
1711         }
1712 
1713         // Sizes.
1714         for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2DArray); sizeNdx++)
1715         {
1716             const string filterGroupName = de::toString(sizes2DArray[sizeNdx].width) + "x" +
1717                                            de::toString(sizes2DArray[sizeNdx].height) + "x" +
1718                                            de::toString(sizes2DArray[sizeNdx].numLayers);
1719             de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1720 
1721             for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1722             {
1723                 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1724                 const char *const filterName        = minFilterModes[filterNdx].name;
1725                 const bool isMipmap                 = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1726                 const string name                   = filterName;
1727                 Texture2DArrayTestCaseParameters testParameters;
1728 
1729                 testParameters.format    = VK_FORMAT_R8G8B8A8_UNORM;
1730                 testParameters.minFilter = minFilter;
1731                 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1732                 testParameters.wrapS     = Sampler::REPEAT_GL;
1733                 testParameters.wrapT     = Sampler::REPEAT_GL;
1734                 testParameters.width     = sizes2DArray[sizeNdx].width;
1735                 testParameters.height    = sizes2DArray[sizeNdx].height;
1736                 testParameters.numLayers = sizes2DArray[sizeNdx].numLayers;
1737 
1738                 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1739                 testParameters.programs.push_back(PROGRAM_2D_ARRAY_FLOAT);
1740 
1741                 filterGroup->addChild(
1742                     new TextureTestCase<Texture2DArrayFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1743             }
1744             sizesGroup->addChild(filterGroup.release());
1745         }
1746 
1747         // Wrap modes.
1748         for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1749         {
1750             de::MovePtr<tcu::TestCaseGroup> minFilterGroup(
1751                 new tcu::TestCaseGroup(testCtx, minFilterModes[minFilterNdx].name));
1752 
1753             for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1754             {
1755                 de::MovePtr<tcu::TestCaseGroup> magFilterGroup(
1756                     new tcu::TestCaseGroup(testCtx, magFilterModes[magFilterNdx].name));
1757 
1758                 for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1759                 {
1760                     de::MovePtr<tcu::TestCaseGroup> wrapSGroup(
1761                         new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name));
1762 
1763                     for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1764                     {
1765                         const string name = wrapModes[wrapTNdx].name;
1766                         Texture2DArrayTestCaseParameters testParameters;
1767 
1768                         testParameters.format    = VK_FORMAT_R8G8B8A8_UNORM;
1769                         testParameters.minFilter = minFilterModes[minFilterNdx].mode;
1770                         testParameters.magFilter = magFilterModes[magFilterNdx].mode;
1771                         testParameters.wrapS     = wrapModes[wrapSNdx].mode;
1772                         testParameters.wrapT     = wrapModes[wrapTNdx].mode;
1773                         testParameters.width     = 123;
1774                         testParameters.height    = 107;
1775                         testParameters.numLayers = 7;
1776 
1777                         testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1778                         testParameters.programs.push_back(PROGRAM_2D_ARRAY_FLOAT);
1779 
1780                         wrapSGroup->addChild(new TextureTestCase<Texture2DArrayFilteringTestInstance>(
1781                             testCtx, name.c_str(), testParameters));
1782                     }
1783                     magFilterGroup->addChild(wrapSGroup.release());
1784                 }
1785                 minFilterGroup->addChild(magFilterGroup.release());
1786             }
1787             combinationsGroup->addChild(minFilterGroup.release());
1788         }
1789 
1790         group2DArray->addChild(formatsGroup.release());
1791         group2DArray->addChild(sizesGroup.release());
1792         group2DArray->addChild(combinationsGroup.release());
1793 
1794         textureFilteringTests->addChild(group2DArray.release());
1795     }
1796 
1797     // 3D texture filtering.
1798     {
1799         de::MovePtr<tcu::TestCaseGroup> group3D(new tcu::TestCaseGroup(testCtx, "3d"));
1800 
1801         de::MovePtr<tcu::TestCaseGroup> formatsGroup(new tcu::TestCaseGroup(testCtx, "formats"));
1802         de::MovePtr<tcu::TestCaseGroup> sizesGroup(new tcu::TestCaseGroup(testCtx, "sizes"));
1803         de::MovePtr<tcu::TestCaseGroup> combinationsGroup(new tcu::TestCaseGroup(testCtx, "combinations"));
1804 
1805         // Formats.
1806         for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(filterableFormatsByType); fmtNdx++)
1807         {
1808             const string filterGroupName = filterableFormatsByType[fmtNdx].name;
1809             de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1810 
1811             for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1812             {
1813                 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1814                 const char *const filterName        = minFilterModes[filterNdx].name;
1815                 const bool isMipmap                 = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1816                 const char *const formatName        = filterableFormatsByType[fmtNdx].name;
1817                 const string name                   = string(formatName) + "_" + filterName;
1818                 Texture3DTestCaseParameters testParameters;
1819 
1820                 testParameters.format    = filterableFormatsByType[fmtNdx].format;
1821                 testParameters.minFilter = minFilter;
1822                 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1823 
1824                 testParameters.wrapS  = Sampler::REPEAT_GL;
1825                 testParameters.wrapT  = Sampler::REPEAT_GL;
1826                 testParameters.wrapR  = Sampler::REPEAT_GL;
1827                 testParameters.width  = 64;
1828                 testParameters.height = 64;
1829                 testParameters.depth  = 64;
1830 
1831                 testParameters.aspectMask = filterableFormatsByType[fmtNdx].aspectMask;
1832                 testParameters.programs.push_back(filterableFormatsByType[fmtNdx].program3D);
1833 
1834                 // Some tests have to be skipped due to the restrictions of the verifiers.
1835                 if (verifierCanBeUsed(testParameters.format, testParameters.minFilter, testParameters.magFilter))
1836                 {
1837                     filterGroup->addChild(
1838                         new TextureTestCase<Texture3DFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1839                 }
1840             }
1841             formatsGroup->addChild(filterGroup.release());
1842         }
1843 
1844         // Sizes.
1845         for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes3D); sizeNdx++)
1846         {
1847             const string filterGroupName = de::toString(sizes3D[sizeNdx].width) + "x" +
1848                                            de::toString(sizes3D[sizeNdx].height) + "x" +
1849                                            de::toString(sizes3D[sizeNdx].depth);
1850             de::MovePtr<tcu::TestCaseGroup> filterGroup(new tcu::TestCaseGroup(testCtx, filterGroupName.c_str()));
1851 
1852             for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); filterNdx++)
1853             {
1854                 const Sampler::FilterMode minFilter = minFilterModes[filterNdx].mode;
1855                 const char *const filterName        = minFilterModes[filterNdx].name;
1856                 const bool isMipmap                 = minFilter != Sampler::NEAREST && minFilter != Sampler::LINEAR;
1857                 const string name                   = filterName;
1858                 Texture3DTestCaseParameters testParameters;
1859 
1860                 testParameters.format    = VK_FORMAT_R8G8B8A8_UNORM;
1861                 testParameters.minFilter = minFilter;
1862                 testParameters.magFilter = isMipmap ? Sampler::LINEAR : minFilter;
1863                 testParameters.wrapS     = Sampler::REPEAT_GL;
1864                 testParameters.wrapT     = Sampler::REPEAT_GL;
1865                 testParameters.wrapR     = Sampler::REPEAT_GL;
1866                 testParameters.width     = sizes3D[sizeNdx].width;
1867                 testParameters.height    = sizes3D[sizeNdx].height;
1868                 testParameters.depth     = sizes3D[sizeNdx].depth;
1869 
1870                 testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1871                 testParameters.programs.push_back(PROGRAM_3D_FLOAT);
1872 
1873                 filterGroup->addChild(
1874                     new TextureTestCase<Texture3DFilteringTestInstance>(testCtx, name.c_str(), testParameters));
1875             }
1876             sizesGroup->addChild(filterGroup.release());
1877         }
1878 
1879         // Wrap modes.
1880         for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(minFilterModes); minFilterNdx++)
1881         {
1882             de::MovePtr<tcu::TestCaseGroup> minFilterGroup(
1883                 new tcu::TestCaseGroup(testCtx, minFilterModes[minFilterNdx].name));
1884 
1885             for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(magFilterModes); magFilterNdx++)
1886             {
1887                 de::MovePtr<tcu::TestCaseGroup> magFilterGroup(
1888                     new tcu::TestCaseGroup(testCtx, magFilterModes[magFilterNdx].name));
1889 
1890                 for (int wrapSNdx = 0; wrapSNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapSNdx++)
1891                 {
1892                     de::MovePtr<tcu::TestCaseGroup> wrapSGroup(
1893                         new tcu::TestCaseGroup(testCtx, wrapModes[wrapSNdx].name));
1894 
1895                     for (int wrapTNdx = 0; wrapTNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapTNdx++)
1896                     {
1897                         de::MovePtr<tcu::TestCaseGroup> wrapTGroup(
1898                             new tcu::TestCaseGroup(testCtx, wrapModes[wrapTNdx].name));
1899 
1900                         for (int wrapRNdx = 0; wrapRNdx < DE_LENGTH_OF_ARRAY(wrapModes); wrapRNdx++)
1901                         {
1902                             const string name = wrapModes[wrapRNdx].name;
1903                             Texture3DTestCaseParameters testParameters;
1904 
1905                             testParameters.format    = VK_FORMAT_R8G8B8A8_UNORM;
1906                             testParameters.minFilter = minFilterModes[minFilterNdx].mode;
1907                             testParameters.magFilter = magFilterModes[magFilterNdx].mode;
1908                             testParameters.wrapS     = wrapModes[wrapSNdx].mode;
1909                             testParameters.wrapT     = wrapModes[wrapTNdx].mode;
1910                             testParameters.wrapR     = wrapModes[wrapRNdx].mode;
1911                             testParameters.width     = 63;
1912                             testParameters.height    = 57;
1913                             testParameters.depth     = 67;
1914 
1915                             testParameters.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
1916                             testParameters.programs.push_back(PROGRAM_3D_FLOAT);
1917 
1918                             wrapTGroup->addChild(new TextureTestCase<Texture3DFilteringTestInstance>(
1919                                 testCtx, name.c_str(), testParameters));
1920                         }
1921                         wrapSGroup->addChild(wrapTGroup.release());
1922                     }
1923                     magFilterGroup->addChild(wrapSGroup.release());
1924                 }
1925                 minFilterGroup->addChild(magFilterGroup.release());
1926             }
1927             combinationsGroup->addChild(minFilterGroup.release());
1928         }
1929 
1930         group3D->addChild(formatsGroup.release());
1931         group3D->addChild(sizesGroup.release());
1932         group3D->addChild(combinationsGroup.release());
1933 
1934         textureFilteringTests->addChild(group3D.release());
1935     }
1936 }
1937 
createTextureFilteringTests(tcu::TestContext & testCtx)1938 tcu::TestCaseGroup *createTextureFilteringTests(tcu::TestContext &testCtx)
1939 {
1940     return createTestGroup(testCtx, "filtering", populateTextureFilteringTests);
1941 }
1942 
1943 } // namespace texture
1944 } // namespace vkt
1945