xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/pipeline/vktPipelineSamplerTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Imagination Technologies Ltd.
7  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Sampler Tests
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktPipelineSamplerTests.hpp"
28 #include "vktPipelineImageSamplingInstance.hpp"
29 #ifndef CTS_USES_VULKANSC
30 #include "vktPipelineSamplerBorderSwizzleTests.hpp"
31 #endif // CTS_USES_VULKANSC
32 #include "vktPipelineImageUtil.hpp"
33 #include "vktPipelineVertexUtil.hpp"
34 #include "vktTestCase.hpp"
35 
36 #include "vkImageUtil.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkObjUtil.hpp"
40 #include "vkBuilderUtil.hpp"
41 #include "vkBarrierUtil.hpp"
42 #include "vkCmdUtil.hpp"
43 #include "vkPrograms.hpp"
44 #include "vkImageWithMemory.hpp"
45 #include "vkBufferWithMemory.hpp"
46 
47 #include "tcuPlatform.hpp"
48 #include "tcuTextureUtil.hpp"
49 #include "tcuTestLog.hpp"
50 #include "tcuMaybe.hpp"
51 #include "tcuImageCompare.hpp"
52 
53 #include "deStringUtil.hpp"
54 #include "deMemory.h"
55 
56 #include <iomanip>
57 #include <sstream>
58 #include <vector>
59 #include <string>
60 #include <memory>
61 #include <utility>
62 #include <algorithm>
63 
64 namespace vkt
65 {
66 namespace pipeline
67 {
68 
69 using namespace vk;
70 using de::MovePtr;
71 
72 namespace
73 {
74 
75 class SamplerViewType
76 {
77 public:
SamplerViewType(vk::VkImageViewType type,bool normalized=true)78     SamplerViewType(vk::VkImageViewType type, bool normalized = true) : m_viewType(type), m_normalized(normalized)
79     {
80         if (!normalized)
81             DE_ASSERT(type == vk::VK_IMAGE_VIEW_TYPE_2D || type == vk::VK_IMAGE_VIEW_TYPE_1D);
82     }
83 
operator vk::VkImageViewType() const84     operator vk::VkImageViewType() const
85     {
86         return m_viewType;
87     }
88 
isNormalized() const89     bool isNormalized() const
90     {
91         return m_normalized;
92     }
93 
94 private:
95     vk::VkImageViewType m_viewType;
96     bool m_normalized;
97 };
98 
99 class SamplerTest : public vkt::TestCase
100 {
101 public:
102     SamplerTest(tcu::TestContext &testContext, const char *name, PipelineConstructionType pipelineConstructionType,
103                 SamplerViewType imageViewType, VkFormat imageFormat, int imageSize, float samplerLod,
104                 bool separateStencilUsage, bool sampleStencil);
~SamplerTest(void)105     virtual ~SamplerTest(void)
106     {
107     }
108 
109     virtual ImageSamplingInstanceParams getImageSamplingInstanceParams(SamplerViewType imageViewType,
110                                                                        VkFormat imageFormat, int imageSize,
111                                                                        float samplerLod, bool separateStencilUsage,
112                                                                        bool sampleStencil) const;
113 
114     tcu::Vec4 swizzle(tcu::Vec4 inputData, VkComponentMapping componentMapping, float zeroOrOneValue) const;
115     virtual void initPrograms(SourceCollections &sourceCollections) const;
116     virtual void checkSupport(Context &context) const;
117     virtual TestInstance *createInstance(Context &context) const;
118     virtual tcu::UVec2 getRenderSize(SamplerViewType viewType) const;
119     virtual std::vector<Vertex4Tex4> createVertices(void) const;
120     virtual VkSamplerCreateInfo getSamplerCreateInfo(void) const;
121     virtual VkComponentMapping getComponentMapping(void) const;
122 
123     static std::string getGlslSamplerType(const tcu::TextureFormat &format, SamplerViewType type, bool sampleStencil);
124     static tcu::IVec3 getImageSize(SamplerViewType viewType, int size);
125     static int getArraySize(SamplerViewType viewType);
126 
127 protected:
128     PipelineConstructionType m_pipelineConstructionType;
129     SamplerViewType m_imageViewType;
130     VkFormat m_imageFormat;
131     int m_imageSize;
132     float m_samplerLod;
133     bool m_separateStencilUsage;
134     bool m_sampleStencil;
135 };
136 
137 class SamplerMagFilterTest : public SamplerTest
138 {
139 public:
140     SamplerMagFilterTest(tcu::TestContext &testContext, const char *name,
141                          PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType,
142                          VkFormat imageFormat, VkFilter magFilter, bool separateStencilUsage);
~SamplerMagFilterTest(void)143     virtual ~SamplerMagFilterTest(void)
144     {
145     }
146     virtual VkSamplerCreateInfo getSamplerCreateInfo(void) const;
147 
148 private:
149     VkFilter m_magFilter;
150 };
151 
152 class SamplerMinFilterTest : public SamplerTest
153 {
154 public:
155     SamplerMinFilterTest(tcu::TestContext &testContext, const char *name,
156                          PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType,
157                          VkFormat imageFormat, VkFilter minFilter, bool separateStencilUsage);
~SamplerMinFilterTest(void)158     virtual ~SamplerMinFilterTest(void)
159     {
160     }
161     virtual VkSamplerCreateInfo getSamplerCreateInfo(void) const;
162 
163 private:
164     VkFilter m_minFilter;
165 };
166 
167 class SamplerMagReduceFilterTest : public SamplerMagFilterTest
168 {
169 public:
170     SamplerMagReduceFilterTest(tcu::TestContext &testContext, const char *name,
171                                PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType,
172                                VkFormat imageFormat, VkComponentMapping componentMapping,
173                                VkSamplerReductionMode reductionMode, bool separateStencilUsage);
174 
~SamplerMagReduceFilterTest(void)175     virtual ~SamplerMagReduceFilterTest(void)
176     {
177     }
178     virtual VkSamplerCreateInfo getSamplerCreateInfo(void) const;
179     virtual VkComponentMapping getComponentMapping(void) const;
180 
181 private:
182     const VkSamplerReductionModeCreateInfo m_reductionCreaterInfo;
183     VkComponentMapping m_componentMapping;
184 };
185 
186 class SamplerMinReduceFilterTest : public SamplerMinFilterTest
187 {
188 public:
189     SamplerMinReduceFilterTest(tcu::TestContext &testContext, const char *name,
190                                PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType,
191                                VkFormat imageFormat, VkComponentMapping componentMapping,
192                                VkSamplerReductionMode reductionMode, bool separateStencilUsage);
193 
~SamplerMinReduceFilterTest(void)194     virtual ~SamplerMinReduceFilterTest(void)
195     {
196     }
197     virtual VkSamplerCreateInfo getSamplerCreateInfo(void) const;
198     virtual VkComponentMapping getComponentMapping(void) const;
199 
200 private:
201     const VkSamplerReductionModeCreateInfo m_reductionCreaterInfo;
202     VkComponentMapping m_componentMapping;
203 };
204 
205 class SamplerLodTest : public SamplerTest
206 {
207 public:
208     SamplerLodTest(tcu::TestContext &testContext, const char *name, PipelineConstructionType pipelineConstructionType,
209                    SamplerViewType imageViewType, VkFormat imageFormat, VkSamplerMipmapMode mipmapMode, float minLod,
210                    float maxLod, float mipLodBias, float samplerLod, bool separateStencilUsage);
~SamplerLodTest(void)211     virtual ~SamplerLodTest(void)
212     {
213     }
214     virtual VkSamplerCreateInfo getSamplerCreateInfo(void) const;
215     virtual void checkSupport(Context &context) const;
216 
217 private:
218     VkSamplerMipmapMode m_mipmapMode;
219     float m_minLod;
220     float m_maxLod;
221     float m_mipLodBias;
222 };
223 
checkSupport(Context & context) const224 void SamplerLodTest::checkSupport(Context &context) const
225 {
226     SamplerTest::checkSupport(context);
227 
228 #ifndef CTS_USES_VULKANSC
229     if (m_mipLodBias != 0.0f && context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
230         !context.getPortabilitySubsetFeatures().samplerMipLodBias)
231     {
232         TCU_THROW(NotSupportedError,
233                   "VK_KHR_portability_subset: Sampler mipmap LOD bias is not supported by this implementation");
234     }
235 #endif // CTS_USES_VULKANSC
236 }
237 
238 class SamplerAddressModesTest : public SamplerTest
239 {
240 public:
241     SamplerAddressModesTest(tcu::TestContext &testContext, const char *name,
242                             PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType,
243                             VkFormat imageFormat, VkSamplerAddressMode addressU, VkSamplerAddressMode addressV,
244                             VkSamplerAddressMode addressW, VkBorderColor borderColor,
245                             rr::GenericVec4 customBorderColorValue, bool customBorderColorFormatless,
246                             bool separateStencilUsage, bool sampleStencil);
~SamplerAddressModesTest(void)247     virtual ~SamplerAddressModesTest(void)
248     {
249     }
250     virtual tcu::UVec2 getRenderSize(SamplerViewType viewType) const;
251     virtual std::vector<Vertex4Tex4> createVertices(void) const;
252     virtual VkSamplerCreateInfo getSamplerCreateInfo(void) const;
253 
254     VkSamplerCustomBorderColorCreateInfoEXT getSamplerCustomBorderColorCreateInfo(
255         VkFormat format, rr::GenericVec4 customBorderColorValue, bool customBorderColorFormatless) const;
256 
257 private:
258     VkSamplerAddressMode m_addressU;
259     VkSamplerAddressMode m_addressV;
260     VkSamplerAddressMode m_addressW;
261     VkBorderColor m_borderColor;
262 
263     const VkSamplerCustomBorderColorCreateInfoEXT m_customBorderColorCreateInfo;
264 };
265 
266 // SamplerTest
267 
SamplerTest(tcu::TestContext & testContext,const char * name,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,int imageSize,float samplerLod,bool separateStencilUsage,bool sampleStencil)268 SamplerTest::SamplerTest(tcu::TestContext &testContext, const char *name,
269                          PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType,
270                          VkFormat imageFormat, int imageSize, float samplerLod, bool separateStencilUsage,
271                          bool sampleStencil)
272     : vkt::TestCase(testContext, name)
273     , m_pipelineConstructionType(pipelineConstructionType)
274     , m_imageViewType(imageViewType)
275     , m_imageFormat(imageFormat)
276     , m_imageSize(imageSize)
277     , m_samplerLod(samplerLod)
278     , m_separateStencilUsage(separateStencilUsage)
279     , m_sampleStencil(sampleStencil)
280 {
281     // Can't do both at the same time with the current code.
282     DE_ASSERT(!separateStencilUsage || !sampleStencil);
283 }
284 
getImageSamplingInstanceParams(SamplerViewType imageViewType,VkFormat imageFormat,int imageSize,float samplerLod,bool separateStencilUsage,bool sampleStencil) const285 ImageSamplingInstanceParams SamplerTest::getImageSamplingInstanceParams(SamplerViewType imageViewType,
286                                                                         VkFormat imageFormat, int imageSize,
287                                                                         float samplerLod, bool separateStencilUsage,
288                                                                         bool sampleStencil) const
289 {
290     const tcu::UVec2 renderSize               = getRenderSize(imageViewType);
291     const std::vector<Vertex4Tex4> vertices   = createVertices();
292     const VkSamplerCreateInfo samplerParams   = getSamplerCreateInfo();
293     const VkComponentMapping componentMapping = getComponentMapping();
294 
295     const auto isDSFormat  = isDepthStencilFormat(imageFormat);
296     const auto tcuFormat   = (isDSFormat ? mapVkFormat(imageFormat) : tcu::TextureFormat());
297     const auto hasDepth    = (isDSFormat && tcu::hasDepthComponent(tcuFormat.order));
298     const auto hasStencil  = (isDSFormat && tcu::hasStencilComponent(tcuFormat.order));
299     const auto imageAspect = (isDSFormat ? (sampleStencil ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT) :
300                                            VK_IMAGE_ASPECT_COLOR_BIT);
301     const uint32_t mipLevels =
302         (imageViewType.isNormalized() ? static_cast<uint32_t>(deLog2Floor32(imageSize)) + 1u : 1u);
303 
304     DE_UNREF(hasDepth);   // For debug builds.
305     DE_UNREF(hasStencil); // For debug builds.
306     DE_ASSERT(imageAspect != VK_IMAGE_ASPECT_DEPTH_BIT || hasDepth);
307     DE_ASSERT(imageAspect != VK_IMAGE_ASPECT_STENCIL_BIT || hasStencil);
308 
309     const VkImageSubresourceRange subresourceRange = {
310         (VkImageAspectFlags)imageAspect,                   // VkImageAspectFlags aspectMask;
311         0u,                                                // uint32_t baseMipLevel;
312         mipLevels,                                         // uint32_t mipLevels;
313         0u,                                                // uint32_t baseArrayLayer;
314         (uint32_t)SamplerTest::getArraySize(imageViewType) // uint32_t arraySize;
315     };
316 
317     return ImageSamplingInstanceParams(m_pipelineConstructionType, renderSize, imageViewType, imageFormat,
318                                        getImageSize(imageViewType, imageSize), getArraySize(imageViewType),
319                                        componentMapping, subresourceRange, samplerParams, samplerLod, vertices,
320                                        separateStencilUsage);
321 }
322 
checkSupport(Context & context) const323 void SamplerTest::checkSupport(Context &context) const
324 {
325     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
326                                           m_pipelineConstructionType);
327 #ifndef CTS_USES_VULKANSC
328     if (m_imageFormat == VK_FORMAT_A8_UNORM_KHR || m_imageFormat == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR)
329         context.requireDeviceFunctionality("VK_KHR_maintenance5");
330 #endif // CTS_USES_VULKANSC
331     checkSupportImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat,
332                                                                               m_imageSize, m_samplerLod,
333                                                                               m_separateStencilUsage, m_sampleStencil));
334 }
335 
swizzle(tcu::Vec4 inputData,VkComponentMapping componentMapping,float zeroOrOneValue) const336 tcu::Vec4 SamplerTest::swizzle(tcu::Vec4 inputData, VkComponentMapping componentMapping, float zeroOrOneValue) const
337 {
338     // Remove VK_COMPONENT_SWIZZLE_IDENTITY to avoid addressing channelValues[0]
339     const vk::VkComponentMapping nonIdentityMapping = {
340         componentMapping.r == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_R : componentMapping.r,
341         componentMapping.g == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_G : componentMapping.g,
342         componentMapping.b == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_B : componentMapping.b,
343         componentMapping.a == VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_A : componentMapping.a
344 
345     };
346     // array map with enum VkComponentSwizzle
347     const float channelValues[] = {-1.0f,          // impossible
348                                    zeroOrOneValue, // SWIZZLE_0
349                                    zeroOrOneValue, // SWIZZLE_1
350                                    inputData.x(),  inputData.y(), inputData.z(), inputData.w(), -1.0f};
351 
352     return tcu::Vec4(channelValues[nonIdentityMapping.r], channelValues[nonIdentityMapping.g],
353                      channelValues[nonIdentityMapping.b], channelValues[nonIdentityMapping.a]);
354 }
355 
initPrograms(SourceCollections & sourceCollections) const356 void SamplerTest::initPrograms(SourceCollections &sourceCollections) const
357 {
358     std::ostringstream vertexSrc;
359     std::ostringstream fragmentSrc;
360     const char *texCoordSwizzle = DE_NULL;
361     tcu::TextureFormat format   = (isCompressedFormat(m_imageFormat)) ?
362                                       tcu::getUncompressedFormat(mapVkCompressedFormat(m_imageFormat)) :
363                                       mapVkFormat(m_imageFormat);
364     tcu::Vec4 lookupScale;
365     tcu::Vec4 lookupBias;
366 
367     getLookupScaleBias(m_imageFormat, lookupScale, lookupBias, m_sampleStencil);
368 
369     tcu::Vec4 swizzledScale = swizzle(lookupScale, getComponentMapping(), 1.0f);
370     tcu::Vec4 swizzledBias  = swizzle(lookupBias, getComponentMapping(), 0.0f);
371 
372     switch (m_imageViewType)
373     {
374     case VK_IMAGE_VIEW_TYPE_1D:
375         texCoordSwizzle = "x";
376         break;
377     case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
378     case VK_IMAGE_VIEW_TYPE_2D:
379         texCoordSwizzle = "xy";
380         break;
381     case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
382     case VK_IMAGE_VIEW_TYPE_3D:
383     case VK_IMAGE_VIEW_TYPE_CUBE:
384         texCoordSwizzle = "xyz";
385         break;
386     case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
387         texCoordSwizzle = "xyzw";
388         break;
389     default:
390         DE_ASSERT(false);
391         break;
392     }
393 
394     vertexSrc << "#version 440\n"
395               << "layout(location = 0) in vec4 position;\n"
396               << "layout(location = 1) in vec4 texCoords;\n"
397               << "layout(location = 0) out highp vec4 vtxTexCoords;\n"
398               << "out gl_PerVertex {\n"
399               << "    vec4 gl_Position;\n"
400               << "};\n"
401               << "void main (void)\n"
402               << "{\n"
403               << "    gl_Position = position;\n"
404               << "    vtxTexCoords = texCoords;\n"
405               << "}\n";
406 
407     fragmentSrc << "#version 440\n"
408                 << "layout(set = 0, binding = 0) uniform highp "
409                 << getGlslSamplerType(format, m_imageViewType, m_sampleStencil) << " texSampler;\n"
410                 << "layout(location = 0) in highp vec4 vtxTexCoords;\n"
411                 << "layout(location = 0) out highp vec4 fragColor;\n"
412                 << "void main (void)\n"
413                 << "{\n"
414                 << "    fragColor = ";
415 
416     if (m_samplerLod > 0.0f || !m_imageViewType.isNormalized())
417     {
418         DE_ASSERT(m_imageViewType.isNormalized() || (m_samplerLod == 0.0f && !m_imageViewType.isNormalized()));
419         fragmentSrc << "textureLod(texSampler, vtxTexCoords." << texCoordSwizzle << ", " << std::fixed << m_samplerLod
420                     << ")";
421     }
422     else
423     {
424         fragmentSrc << "texture(texSampler, vtxTexCoords." << texCoordSwizzle << ")" << std::fixed;
425     }
426 
427     fragmentSrc << " * vec4" << std::scientific << swizzledScale << " + vec4" << swizzledBias << ";\n"
428                 << "}\n";
429 
430     sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str());
431     sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str());
432 }
433 
createInstance(Context & context) const434 TestInstance *SamplerTest::createInstance(Context &context) const
435 {
436     return new ImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat,
437                                                                              m_imageSize, m_samplerLod,
438                                                                              m_separateStencilUsage, m_sampleStencil));
439 }
440 
getRenderSize(SamplerViewType viewType) const441 tcu::UVec2 SamplerTest::getRenderSize(SamplerViewType viewType) const
442 {
443     if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D)
444     {
445         return tcu::UVec2(16u, 16u);
446     }
447     else
448     {
449         return tcu::UVec2(16u * 3u, 16u * 2u);
450     }
451 }
452 
createVertices(void) const453 std::vector<Vertex4Tex4> SamplerTest::createVertices(void) const
454 {
455     std::vector<Vertex4Tex4> vertices = createTestQuadMosaic(m_imageViewType);
456     // Adjust texture coordinate to avoid doing NEAREST filtering exactly on texel boundaries.
457     // TODO: Would be nice to base this on number of texels and subtexel precision. But this
458     // seems to work.
459     for (unsigned int i = 0; i < vertices.size(); ++i)
460     {
461         vertices[i].texCoord += tcu::Vec4(0.002f, 0.002f, 0.002f, 0.0f);
462         if (!m_imageViewType.isNormalized())
463         {
464             const float imageSize = static_cast<float>(m_imageSize);
465             for (int j = 0; j < tcu::Vec4::SIZE; ++j)
466                 vertices[i].texCoord[j] *= imageSize;
467         }
468     }
469     return vertices;
470 }
471 
getSamplerCreateInfo(void) const472 VkSamplerCreateInfo SamplerTest::getSamplerCreateInfo(void) const
473 {
474     const VkSamplerCreateInfo defaultSamplerParams = {
475         VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,           // VkStructureType sType;
476         DE_NULL,                                         // const void* pNext;
477         0u,                                              // VkSamplerCreateFlags flags;
478         VK_FILTER_NEAREST,                               // VkFilter magFilter;
479         VK_FILTER_NEAREST,                               // VkFilter minFilter;
480         VK_SAMPLER_MIPMAP_MODE_NEAREST,                  // VkSamplerMipmapMode mipmapMode;
481         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,           // VkSamplerAddressMode addressModeU;
482         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,           // VkSamplerAddressMode addressModeV;
483         VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,           // VkSamplerAddressMode addressModeW;
484         0.0f,                                            // float mipLodBias;
485         VK_FALSE,                                        // VkBool32 anisotropyEnable;
486         1.0f,                                            // float maxAnisotropy;
487         false,                                           // VkBool32 compareEnable;
488         VK_COMPARE_OP_NEVER,                             // VkCompareOp compareOp;
489         0.0f,                                            // float minLod;
490         (m_imageViewType.isNormalized() ? 0.25f : 0.0f), // float maxLod;
491         getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, m_imageFormat,
492                              m_sampleStencil), // VkBorderColor borderColor;
493         !m_imageViewType.isNormalized(),       // VkBool32 unnormalizedCoordinates;
494     };
495 
496     return defaultSamplerParams;
497 }
498 
getComponentMapping(void) const499 VkComponentMapping SamplerTest::getComponentMapping(void) const
500 {
501     const VkComponentMapping componentMapping = {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B,
502                                                  VK_COMPONENT_SWIZZLE_A};
503     return componentMapping;
504 }
505 
getGlslSamplerType(const tcu::TextureFormat & format,SamplerViewType type,bool sampleStencil)506 std::string SamplerTest::getGlslSamplerType(const tcu::TextureFormat &format, SamplerViewType type, bool sampleStencil)
507 {
508     std::ostringstream samplerType;
509 
510     if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER || sampleStencil)
511         samplerType << "u";
512     else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
513         samplerType << "i";
514 
515     switch (type)
516     {
517     case VK_IMAGE_VIEW_TYPE_1D:
518         samplerType << "sampler1D";
519         break;
520 
521     case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
522         samplerType << "sampler1DArray";
523         break;
524 
525     case VK_IMAGE_VIEW_TYPE_2D:
526         samplerType << "sampler2D";
527         break;
528 
529     case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
530         samplerType << "sampler2DArray";
531         break;
532 
533     case VK_IMAGE_VIEW_TYPE_3D:
534         samplerType << "sampler3D";
535         break;
536 
537     case VK_IMAGE_VIEW_TYPE_CUBE:
538         samplerType << "samplerCube";
539         break;
540 
541     case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
542         samplerType << "samplerCubeArray";
543         break;
544 
545     default:
546         DE_FATAL("Unknown image view type");
547         break;
548     }
549 
550     return samplerType.str();
551 }
552 
getImageSize(SamplerViewType viewType,int size)553 tcu::IVec3 SamplerTest::getImageSize(SamplerViewType viewType, int size)
554 {
555     switch (viewType)
556     {
557     case VK_IMAGE_VIEW_TYPE_1D:
558     case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
559         return tcu::IVec3(size, 1, 1);
560 
561     case VK_IMAGE_VIEW_TYPE_3D:
562         return tcu::IVec3(size, size, 4);
563 
564     default:
565         break;
566     }
567 
568     return tcu::IVec3(size, size, 1);
569 }
570 
getArraySize(SamplerViewType viewType)571 int SamplerTest::getArraySize(SamplerViewType viewType)
572 {
573     switch (viewType)
574     {
575     case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
576     case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
577     case VK_IMAGE_VIEW_TYPE_CUBE:
578         return 6;
579 
580     case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
581         return 36;
582 
583     default:
584         break;
585     }
586 
587     return 1;
588 }
589 
590 // SamplerMagFilterTest
591 
SamplerMagFilterTest(tcu::TestContext & testContext,const char * name,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,VkFilter magFilter,bool separateStencilUsage)592 SamplerMagFilterTest::SamplerMagFilterTest(tcu::TestContext &testContext, const char *name,
593                                            PipelineConstructionType pipelineConstructionType,
594                                            SamplerViewType imageViewType, VkFormat imageFormat, VkFilter magFilter,
595                                            bool separateStencilUsage)
596     : SamplerTest(testContext, name, pipelineConstructionType, imageViewType, imageFormat, 8, 0.0f,
597                   separateStencilUsage, false)
598     , m_magFilter(magFilter)
599 {
600 }
601 
getSamplerCreateInfo(void) const602 VkSamplerCreateInfo SamplerMagFilterTest::getSamplerCreateInfo(void) const
603 {
604     VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
605     samplerParams.magFilter           = m_magFilter;
606 
607     return samplerParams;
608 }
609 
610 // SamplerMinFilterTest
611 
SamplerMinFilterTest(tcu::TestContext & testContext,const char * name,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,VkFilter minFilter,bool separateStencilUsage)612 SamplerMinFilterTest::SamplerMinFilterTest(tcu::TestContext &testContext, const char *name,
613                                            PipelineConstructionType pipelineConstructionType,
614                                            SamplerViewType imageViewType, VkFormat imageFormat, VkFilter minFilter,
615                                            bool separateStencilUsage)
616     : SamplerTest(testContext, name, pipelineConstructionType, imageViewType, imageFormat, 32, 0.0f,
617                   separateStencilUsage, false)
618     , m_minFilter(minFilter)
619 {
620 }
621 
getSamplerCreateInfo(void) const622 VkSamplerCreateInfo SamplerMinFilterTest::getSamplerCreateInfo(void) const
623 {
624     VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
625     samplerParams.minFilter           = m_minFilter;
626     // set minLod to epsilon, to force use of the minFilter
627     samplerParams.minLod = 0.01f;
628 
629     return samplerParams;
630 }
631 
632 namespace
633 {
634 
getSamplerReductionCreateInfo(VkSamplerReductionMode reductionMode)635 VkSamplerReductionModeCreateInfo getSamplerReductionCreateInfo(VkSamplerReductionMode reductionMode)
636 {
637     const VkSamplerReductionModeCreateInfo ret = {
638         VK_STRUCTURE_TYPE_SAMPLER_REDUCTION_MODE_CREATE_INFO, // VkStructureType                sType
639         DE_NULL,                                              // const void*                    pNext
640         reductionMode                                         // VkSamplerReductionMode        reductionMode
641     };
642     return ret;
643 }
644 
645 } // namespace
646 
647 // SamplerMagReduceFilterTest
648 
SamplerMagReduceFilterTest(tcu::TestContext & testContext,const char * name,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,VkComponentMapping componentMapping,VkSamplerReductionMode reductionMode,bool separateStencilUsage)649 SamplerMagReduceFilterTest::SamplerMagReduceFilterTest(tcu::TestContext &testContext, const char *name,
650                                                        PipelineConstructionType pipelineConstructionType,
651                                                        SamplerViewType imageViewType, VkFormat imageFormat,
652                                                        VkComponentMapping componentMapping,
653                                                        VkSamplerReductionMode reductionMode, bool separateStencilUsage)
654     : SamplerMagFilterTest(testContext, name, pipelineConstructionType, imageViewType, imageFormat, VK_FILTER_LINEAR,
655                            separateStencilUsage)
656     , m_reductionCreaterInfo(getSamplerReductionCreateInfo(reductionMode))
657     , m_componentMapping(componentMapping)
658 {
659 }
660 
getSamplerCreateInfo(void) const661 VkSamplerCreateInfo SamplerMagReduceFilterTest::getSamplerCreateInfo(void) const
662 {
663     VkSamplerCreateInfo samplerParams = SamplerMagFilterTest::getSamplerCreateInfo();
664 
665     samplerParams.pNext = &m_reductionCreaterInfo;
666 
667     return samplerParams;
668 }
669 
getComponentMapping(void) const670 VkComponentMapping SamplerMagReduceFilterTest::getComponentMapping(void) const
671 {
672     return m_componentMapping;
673 }
674 
675 // SamplerMinReduceFilterTest
676 
SamplerMinReduceFilterTest(tcu::TestContext & testContext,const char * name,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,VkComponentMapping componentMapping,VkSamplerReductionMode reductionMode,bool separateStencilUsage)677 SamplerMinReduceFilterTest::SamplerMinReduceFilterTest(tcu::TestContext &testContext, const char *name,
678                                                        PipelineConstructionType pipelineConstructionType,
679                                                        SamplerViewType imageViewType, VkFormat imageFormat,
680                                                        VkComponentMapping componentMapping,
681                                                        VkSamplerReductionMode reductionMode, bool separateStencilUsage)
682     : SamplerMinFilterTest(testContext, name, pipelineConstructionType, imageViewType, imageFormat, VK_FILTER_LINEAR,
683                            separateStencilUsage)
684     , m_reductionCreaterInfo(getSamplerReductionCreateInfo(reductionMode))
685     , m_componentMapping(componentMapping)
686 {
687 }
688 
getSamplerCreateInfo(void) const689 VkSamplerCreateInfo SamplerMinReduceFilterTest::getSamplerCreateInfo(void) const
690 {
691     VkSamplerCreateInfo samplerParams = SamplerMinFilterTest::getSamplerCreateInfo();
692 
693     samplerParams.pNext = &m_reductionCreaterInfo;
694 
695     return samplerParams;
696 }
697 
getComponentMapping(void) const698 VkComponentMapping SamplerMinReduceFilterTest::getComponentMapping(void) const
699 {
700     return m_componentMapping;
701 }
702 
703 // SamplerLodTest
704 
SamplerLodTest(tcu::TestContext & testContext,const char * name,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,VkSamplerMipmapMode mipmapMode,float minLod,float maxLod,float mipLodBias,float samplerLod,bool separateStencilUsage)705 SamplerLodTest::SamplerLodTest(tcu::TestContext &testContext, const char *name,
706                                PipelineConstructionType pipelineConstructionType, SamplerViewType imageViewType,
707                                VkFormat imageFormat, VkSamplerMipmapMode mipmapMode, float minLod, float maxLod,
708                                float mipLodBias, float samplerLod, bool separateStencilUsage)
709     : SamplerTest(testContext, name, pipelineConstructionType, imageViewType, imageFormat, 32, samplerLod,
710                   separateStencilUsage, false)
711     , m_mipmapMode(mipmapMode)
712     , m_minLod(minLod)
713     , m_maxLod(maxLod)
714     , m_mipLodBias(mipLodBias)
715 {
716 }
717 
getSamplerCreateInfo(void) const718 VkSamplerCreateInfo SamplerLodTest::getSamplerCreateInfo(void) const
719 {
720     VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
721 
722     samplerParams.mipmapMode = m_mipmapMode;
723     samplerParams.minLod     = m_minLod;
724     samplerParams.maxLod     = m_maxLod;
725     samplerParams.mipLodBias = m_mipLodBias;
726 
727     return samplerParams;
728 }
729 
730 // SamplerAddressModesTest
731 
SamplerAddressModesTest(tcu::TestContext & testContext,const char * name,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,VkSamplerAddressMode addressU,VkSamplerAddressMode addressV,VkSamplerAddressMode addressW,VkBorderColor borderColor,rr::GenericVec4 customBorderColorValue,bool customBorderColorFormatless,bool separateStencilUsage,bool sampleStencil)732 SamplerAddressModesTest::SamplerAddressModesTest(
733     tcu::TestContext &testContext, const char *name, PipelineConstructionType pipelineConstructionType,
734     SamplerViewType imageViewType, VkFormat imageFormat, VkSamplerAddressMode addressU, VkSamplerAddressMode addressV,
735     VkSamplerAddressMode addressW, VkBorderColor borderColor, rr::GenericVec4 customBorderColorValue,
736     bool customBorderColorFormatless, bool separateStencilUsage, bool sampleStencil)
737     : SamplerTest(testContext, name, pipelineConstructionType, imageViewType, imageFormat, 8, 0.0f,
738                   separateStencilUsage, sampleStencil)
739     , m_addressU(addressU)
740     , m_addressV(addressV)
741     , m_addressW(addressW)
742     , m_borderColor(borderColor)
743     , m_customBorderColorCreateInfo(
744           getSamplerCustomBorderColorCreateInfo(imageFormat, customBorderColorValue, customBorderColorFormatless))
745 {
746 }
747 
getRenderSize(SamplerViewType viewType) const748 tcu::UVec2 SamplerAddressModesTest::getRenderSize(SamplerViewType viewType) const
749 {
750     return 4u * SamplerTest::getRenderSize(viewType);
751 }
752 
createVertices(void) const753 std::vector<Vertex4Tex4> SamplerAddressModesTest::createVertices(void) const
754 {
755     std::vector<Vertex4Tex4> vertices = SamplerTest::createVertices();
756 
757     switch (m_imageViewType)
758     {
759     case VK_IMAGE_VIEW_TYPE_1D:
760     case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
761         for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
762             vertices[vertexNdx].texCoord.x() = (vertices[vertexNdx].texCoord.x() - 0.5f) * 4.0f;
763 
764         break;
765 
766     case VK_IMAGE_VIEW_TYPE_2D:
767     case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
768         for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
769             vertices[vertexNdx].texCoord.xy() = (vertices[vertexNdx].texCoord.swizzle(0, 1) - tcu::Vec2(0.5f)) * 4.0f;
770 
771         break;
772 
773     case VK_IMAGE_VIEW_TYPE_3D:
774         for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++)
775             vertices[vertexNdx].texCoord.xyz() =
776                 (vertices[vertexNdx].texCoord.swizzle(0, 1, 2) - tcu::Vec3(0.5f)) * 4.0f;
777 
778         break;
779 
780     case VK_IMAGE_VIEW_TYPE_CUBE:
781     case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
782         break;
783 
784     default:
785         DE_ASSERT(false);
786     }
787 
788     return vertices;
789 }
790 
getSamplerCreateInfo(void) const791 VkSamplerCreateInfo SamplerAddressModesTest::getSamplerCreateInfo(void) const
792 {
793     VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo();
794     samplerParams.addressModeU        = m_addressU;
795     samplerParams.addressModeV        = m_addressV;
796     samplerParams.addressModeW        = m_addressW;
797     samplerParams.borderColor         = m_borderColor;
798 
799     if (m_borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT || m_borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT)
800     {
801         samplerParams.pNext = &m_customBorderColorCreateInfo;
802     }
803 
804     return samplerParams;
805 }
806 
getSamplerCustomBorderColorCreateInfo(VkFormat format,rr::GenericVec4 customBorderColorValue,bool customBorderColorFormatless) const807 VkSamplerCustomBorderColorCreateInfoEXT SamplerAddressModesTest::getSamplerCustomBorderColorCreateInfo(
808     VkFormat format, rr::GenericVec4 customBorderColorValue, bool customBorderColorFormatless) const
809 {
810     const VkSamplerCustomBorderColorCreateInfoEXT defaultSamplerCustomBorderColorParams = {
811         VK_STRUCTURE_TYPE_SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT, DE_NULL, mapVkColor(customBorderColorValue),
812         customBorderColorFormatless ? VK_FORMAT_UNDEFINED : format};
813 
814     return defaultSamplerCustomBorderColorParams;
815 }
816 
817 // Utilities to create test nodes
818 
getFormatCaseName(const VkFormat format)819 std::string getFormatCaseName(const VkFormat format)
820 {
821     const std::string fullName = getFormatName(format);
822 
823     DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_"));
824 
825     return de::toLower(fullName.substr(10));
826 }
827 
createSamplerMagFilterTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)828 MovePtr<tcu::TestCaseGroup> createSamplerMagFilterTests(tcu::TestContext &testCtx,
829                                                         PipelineConstructionType pipelineConstructionType,
830                                                         SamplerViewType imageViewType, VkFormat imageFormat,
831                                                         bool separateStencilUsage)
832 {
833     // Tests for magnification filter
834     MovePtr<tcu::TestCaseGroup> samplerMagFilterTests(new tcu::TestCaseGroup(testCtx, "mag_filter"));
835 
836     if (imageViewType.isNormalized() &&
837         (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat))))
838         // Magnifies image using VK_FILTER_LINEAR
839         samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "linear", pipelineConstructionType,
840                                                                  imageViewType, imageFormat, VK_FILTER_LINEAR,
841                                                                  separateStencilUsage));
842     // Magnifies image using VK_FILTER_NEAREST
843     samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "nearest", pipelineConstructionType,
844                                                              imageViewType, imageFormat, VK_FILTER_NEAREST,
845                                                              separateStencilUsage));
846 
847     return samplerMagFilterTests;
848 }
849 
createSamplerMinFilterTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)850 MovePtr<tcu::TestCaseGroup> createSamplerMinFilterTests(tcu::TestContext &testCtx,
851                                                         PipelineConstructionType pipelineConstructionType,
852                                                         SamplerViewType imageViewType, VkFormat imageFormat,
853                                                         bool separateStencilUsage)
854 {
855     // Tests for minification filter
856     MovePtr<tcu::TestCaseGroup> samplerMinFilterTests(new tcu::TestCaseGroup(testCtx, "min_filter"));
857 
858     if (imageViewType.isNormalized() &&
859         (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat))))
860         // Minifies image using VK_FILTER_LINEAR
861         samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "linear", pipelineConstructionType,
862                                                                  imageViewType, imageFormat, VK_FILTER_LINEAR,
863                                                                  separateStencilUsage));
864     // Minifies image using VK_FILTER_NEAREST
865     samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "nearest", pipelineConstructionType,
866                                                              imageViewType, imageFormat, VK_FILTER_NEAREST,
867                                                              separateStencilUsage));
868 
869     return samplerMinFilterTests;
870 }
871 
872 const VkComponentMapping reduceFilterComponentMappings[] = {
873     // filterMinmaxImageComponentMapping  == false - compatible mappings:
874     {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO},
875     {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO},
876 
877     // other mappings
878     {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A},
879     {VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_A},
880     {VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R},
881 };
882 
getShortComponentSwizzleName(VkComponentSwizzle componentSwizzle)883 static std::string getShortComponentSwizzleName(VkComponentSwizzle componentSwizzle)
884 {
885     const std::string fullName = getComponentSwizzleName(componentSwizzle);
886     const char *prefix         = "VK_COMPONENT_SWIZZLE_";
887 
888     DE_ASSERT(de::beginsWith(fullName, prefix));
889 
890     return de::toLower(fullName.substr(deStrnlen(prefix, -1)));
891 }
892 
getComponentMappingGroupName(const VkComponentMapping & componentMapping)893 static std::string getComponentMappingGroupName(const VkComponentMapping &componentMapping)
894 {
895     std::ostringstream name;
896 
897     name << "comp_";
898 
899     name << getShortComponentSwizzleName(componentMapping.r) << "_" << getShortComponentSwizzleName(componentMapping.g)
900          << "_" << getShortComponentSwizzleName(componentMapping.b) << "_"
901          << getShortComponentSwizzleName(componentMapping.a);
902 
903     return name.str();
904 }
905 
createSamplerMagReduceFilterTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)906 MovePtr<tcu::TestCaseGroup> createSamplerMagReduceFilterTests(tcu::TestContext &testCtx,
907                                                               PipelineConstructionType pipelineConstructionType,
908                                                               SamplerViewType imageViewType, VkFormat imageFormat,
909                                                               bool separateStencilUsage)
910 {
911     MovePtr<tcu::TestCaseGroup> samplerMagReduceFilterTests(new tcu::TestCaseGroup(testCtx, "mag_reduce"));
912 
913     for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(reduceFilterComponentMappings); ++i)
914     {
915         const VkComponentMapping &mapping = reduceFilterComponentMappings[i];
916 
917         MovePtr<tcu::TestCaseGroup> componentGroup(
918             new tcu::TestCaseGroup(testCtx, getComponentMappingGroupName(mapping).c_str()));
919 
920         if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
921         {
922             // Magnifies image using VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE
923             componentGroup->addChild(new SamplerMagReduceFilterTest(
924                 testCtx, "average", pipelineConstructionType, imageViewType, imageFormat, mapping,
925                 VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, separateStencilUsage));
926         }
927         // Magnifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MIN
928         componentGroup->addChild(new SamplerMagReduceFilterTest(testCtx, "min", pipelineConstructionType, imageViewType,
929                                                                 imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MIN,
930                                                                 separateStencilUsage));
931         // Magnifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MAX
932         componentGroup->addChild(new SamplerMagReduceFilterTest(testCtx, "max", pipelineConstructionType, imageViewType,
933                                                                 imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MAX,
934                                                                 separateStencilUsage));
935         samplerMagReduceFilterTests->addChild(componentGroup.release());
936     }
937     return samplerMagReduceFilterTests;
938 }
939 
createSamplerMinReduceFilterTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)940 MovePtr<tcu::TestCaseGroup> createSamplerMinReduceFilterTests(tcu::TestContext &testCtx,
941                                                               PipelineConstructionType pipelineConstructionType,
942                                                               SamplerViewType imageViewType, VkFormat imageFormat,
943                                                               bool separateStencilUsage)
944 {
945     MovePtr<tcu::TestCaseGroup> samplerMinReduceFilterTests(new tcu::TestCaseGroup(testCtx, "min_reduce"));
946 
947     for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(reduceFilterComponentMappings); ++i)
948     {
949         const VkComponentMapping &mapping = reduceFilterComponentMappings[i];
950 
951         MovePtr<tcu::TestCaseGroup> componentGroup(
952             new tcu::TestCaseGroup(testCtx, getComponentMappingGroupName(mapping).c_str()));
953 
954         if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
955         {
956             // Minifies image using VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE
957             componentGroup->addChild(new SamplerMinReduceFilterTest(
958                 testCtx, "average", pipelineConstructionType, imageViewType, imageFormat, mapping,
959                 VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE, separateStencilUsage));
960         }
961         // Minifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MIN
962         componentGroup->addChild(new SamplerMinReduceFilterTest(testCtx, "min", pipelineConstructionType, imageViewType,
963                                                                 imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MIN,
964                                                                 separateStencilUsage));
965         // Minifies and reduces image using VK_SAMPLER_REDUCTION_MODE_MAX
966         componentGroup->addChild(new SamplerMinReduceFilterTest(testCtx, "max", pipelineConstructionType, imageViewType,
967                                                                 imageFormat, mapping, VK_SAMPLER_REDUCTION_MODE_MAX,
968                                                                 separateStencilUsage));
969         samplerMinReduceFilterTests->addChild(componentGroup.release());
970     }
971     return samplerMinReduceFilterTests;
972 }
973 
createSamplerLodTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,VkSamplerMipmapMode mipmapMode,bool separateStencilUsage)974 MovePtr<tcu::TestCaseGroup> createSamplerLodTests(tcu::TestContext &testCtx,
975                                                   PipelineConstructionType pipelineConstructionType,
976                                                   SamplerViewType imageViewType, VkFormat imageFormat,
977                                                   VkSamplerMipmapMode mipmapMode, bool separateStencilUsage)
978 {
979     struct TestCaseConfig
980     {
981         const char *name;
982         float minLod;
983         float maxLod;
984         float mipLodBias;
985         float lod;
986     };
987 
988     TestCaseConfig testCaseConfigs[] = {
989         // minLod = 3, maxLod = 3, mipLodBias = 0, lod = 0
990         {"equal_min_3_max_3", 3.0f, 3.0f, 0.0f, 0.0f},
991         // minLod = 1, maxLod = 5, mipLodBias = 0, lod = 0
992         {"select_min_1", 1.0f, 5.0f, 0.0f, 0.0f},
993         // minLod = 0, maxLod = 4, mipLodBias = 0, lod = 5
994         {"select_max_4", 0.0f, 4.0f, 0.0f, 5.0f},
995         // minLod = 0, maxLod = 2.1, mipLodBias = 5.0, lod = 0
996         {"select_bias_2_1", 0.0f, 2.1f, 5.0f, 0.0f},
997         // minLod = 0, maxLod = 5, mipLodBias = 2.5, lod = 0
998         {"select_bias_2_5", 0.0f, 5.0f, 2.5f, 0.00001f},
999         // minLod = 0, maxLod = 5, mipLodBias = -0.9, lod = 4.0
1000         {"select_bias_3_1", 0.0f, 5.0f, -0.9f, 4.0f},
1001         // minLod = 0, maxLod = 5, mipLodBias = 3.0, lod = 0.7
1002         {"select_bias_3_7", 0.0f, 5.0f, 3.0f, 0.7f},
1003     };
1004 
1005     MovePtr<tcu::TestCaseGroup> samplerLodTests(new tcu::TestCaseGroup(testCtx, "lod"));
1006 
1007     for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++)
1008     {
1009         const TestCaseConfig &config = testCaseConfigs[configNdx];
1010 
1011         samplerLodTests->addChild(new SamplerLodTest(testCtx, config.name, pipelineConstructionType, imageViewType,
1012                                                      imageFormat, mipmapMode, config.minLod, config.maxLod,
1013                                                      config.mipLodBias, config.lod, separateStencilUsage));
1014     }
1015 
1016     return samplerLodTests;
1017 }
1018 
createSamplerMipmapTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)1019 MovePtr<tcu::TestCaseGroup> createSamplerMipmapTests(tcu::TestContext &testCtx,
1020                                                      PipelineConstructionType pipelineConstructionType,
1021                                                      SamplerViewType imageViewType, VkFormat imageFormat,
1022                                                      bool separateStencilUsage)
1023 {
1024     MovePtr<tcu::TestCaseGroup> samplerMipmapTests(new tcu::TestCaseGroup(testCtx, "mipmap"));
1025 
1026     // Mipmap mode: nearest
1027     MovePtr<tcu::TestCaseGroup> mipmapNearestTests(new tcu::TestCaseGroup(testCtx, "nearest"));
1028     mipmapNearestTests->addChild(createSamplerLodTests(testCtx, pipelineConstructionType, imageViewType, imageFormat,
1029                                                        VK_SAMPLER_MIPMAP_MODE_NEAREST, separateStencilUsage)
1030                                      .release());
1031     samplerMipmapTests->addChild(mipmapNearestTests.release());
1032 
1033     // Mipmap mode: linear
1034     if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat)))
1035     {
1036         MovePtr<tcu::TestCaseGroup> mipmapLinearTests(new tcu::TestCaseGroup(testCtx, "linear"));
1037         mipmapLinearTests->addChild(createSamplerLodTests(testCtx, pipelineConstructionType, imageViewType, imageFormat,
1038                                                           VK_SAMPLER_MIPMAP_MODE_LINEAR, separateStencilUsage)
1039                                         .release());
1040         samplerMipmapTests->addChild(mipmapLinearTests.release());
1041     }
1042 
1043     return samplerMipmapTests;
1044 }
1045 
getAddressModesCaseName(VkSamplerAddressMode u,VkSamplerAddressMode v,VkSamplerAddressMode w,BorderColor border,tcu::IVec4 customIntValue,bool formatless,bool sampleStencil)1046 std::string getAddressModesCaseName(VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w,
1047                                     BorderColor border, tcu::IVec4 customIntValue, bool formatless, bool sampleStencil)
1048 {
1049     static const char *borderColorNames[BORDER_COLOR_COUNT] = {"opaque_black", "opaque_white", "transparent_black",
1050                                                                "custom"};
1051 
1052     std::ostringstream caseName;
1053 
1054     if (u == v && v == w)
1055     {
1056         const std::string fullName = getSamplerAddressModeName(u);
1057         DE_ASSERT(de::beginsWith(fullName, "VK_SAMPLER_ADDRESS_"));
1058 
1059         caseName << "all_";
1060         caseName << de::toLower(fullName.substr(19));
1061 
1062         if (u == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)
1063         {
1064             caseName << "_" << borderColorNames[border];
1065         }
1066     }
1067     else
1068     {
1069         const std::string fullNameU = getSamplerAddressModeName(u);
1070         const std::string fullNameV = getSamplerAddressModeName(v);
1071         const std::string fullNameW = getSamplerAddressModeName(w);
1072 
1073         DE_ASSERT(de::beginsWith(fullNameU, "VK_SAMPLER_ADDRESS_"));
1074         DE_ASSERT(de::beginsWith(fullNameV, "VK_SAMPLER_ADDRESS_"));
1075         DE_ASSERT(de::beginsWith(fullNameW, "VK_SAMPLER_ADDRESS_"));
1076 
1077         caseName << "uvw"
1078                  << "_" << de::toLower(fullNameU.substr(19)) << "_" << de::toLower(fullNameV.substr(19)) << "_"
1079                  << de::toLower(fullNameW.substr(19));
1080     }
1081 
1082     if (border == BORDER_COLOR_CUSTOM)
1083     {
1084         caseName << "_";
1085         for (int i = 0; i < 4; i++)
1086             caseName << customIntValue[i];
1087 
1088         if (formatless)
1089             caseName << "_formatless";
1090     }
1091 
1092     if (sampleStencil)
1093         caseName << "_stencil";
1094 
1095     return caseName.str();
1096 }
1097 
createSamplerAddressModesTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,SamplerViewType imageViewType,VkFormat imageFormat,bool separateStencilUsage)1098 MovePtr<tcu::TestCaseGroup> createSamplerAddressModesTests(tcu::TestContext &testCtx,
1099                                                            PipelineConstructionType pipelineConstructionType,
1100                                                            SamplerViewType imageViewType, VkFormat imageFormat,
1101                                                            bool separateStencilUsage)
1102 {
1103     struct TestCaseConfig
1104     {
1105         TestCaseConfig(VkSamplerAddressMode _u, VkSamplerAddressMode _v, VkSamplerAddressMode _w, BorderColor _border,
1106                        bool _customColorFormatless = false, tcu::Vec4 _customColorValueFloat = tcu::Vec4(),
1107                        tcu::IVec4 _customColorValueInt = tcu::IVec4())
1108             : u(_u)
1109             , v(_v)
1110             , w(_w)
1111             , border(_border)
1112             , customColorFormatless(_customColorFormatless)
1113             , customColorValueFloat(_customColorValueFloat)
1114             , customColorValueInt(_customColorValueInt)
1115         {
1116         }
1117 
1118         VkSamplerAddressMode u;
1119         VkSamplerAddressMode v;
1120         VkSamplerAddressMode w;
1121         BorderColor border;
1122         bool customColorFormatless;
1123         tcu::Vec4 customColorValueFloat;
1124         tcu::IVec4 customColorValueInt;
1125     };
1126 
1127     const TestCaseConfig testCaseConfigs[] = {
1128         // All address modes equal
1129         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1130          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_TRANSPARENT_BLACK},
1131         {VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT,
1132          BORDER_COLOR_TRANSPARENT_BLACK},
1133         {VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
1134          VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_TRANSPARENT_BLACK},
1135         {VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,
1136          VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_TRANSPARENT_BLACK},
1137 
1138         // All address modes equal using border color
1139         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
1140          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_TRANSPARENT_BLACK},
1141         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
1142          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_BLACK},
1143         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
1144          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE},
1145 
1146         // Pairwise combinations of address modes not covered by previous tests
1147         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,
1148          VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE},
1149         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
1150          VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE},
1151         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_REPEAT,
1152          VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE},
1153         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1154          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE},
1155         {VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
1156          VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE},
1157         {VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,
1158          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE},
1159         {VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
1160          VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE},
1161         {VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1162          VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE},
1163         {VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT,
1164          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE},
1165         {VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
1166          VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE},
1167         {VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,
1168          VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE},
1169         {VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT,
1170          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE},
1171         {VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT,
1172          BORDER_COLOR_OPAQUE_WHITE},
1173         {VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1174          BORDER_COLOR_OPAQUE_WHITE},
1175         {VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
1176          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE},
1177         {VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
1178          BORDER_COLOR_OPAQUE_WHITE},
1179         {VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,
1180          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE},
1181         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
1182          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE},
1183         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_REPEAT,
1184          BORDER_COLOR_OPAQUE_WHITE},
1185         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT,
1186          VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE},
1187         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT,
1188          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE},
1189         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE,
1190          VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE},
1191 
1192         // Custom border color tests
1193         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
1194          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM, false, tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f),
1195          tcu::IVec4(0, 0, 0, 0)},
1196         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
1197          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM, false, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
1198          tcu::IVec4(0, 0, 1, 1)},
1199         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
1200          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM, false, tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f),
1201          tcu::IVec4(1, 0, 0, 0)},
1202         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
1203          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM, false, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
1204          tcu::IVec4(1, 0, 0, 1)},
1205         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
1206          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM, false, tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f),
1207          tcu::IVec4(1, 0, 1, 1)},
1208         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
1209          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM, false, tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
1210          tcu::IVec4(1, 1, 0, 1)},
1211 
1212         // Custom border color formatless
1213         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
1214          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM, true, tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f),
1215          tcu::IVec4(1, 0, 1, 1)},
1216         {VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER,
1217          VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_CUSTOM, true, tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
1218          tcu::IVec4(1, 1, 0, 1)},
1219     };
1220 
1221     MovePtr<tcu::TestCaseGroup> samplerAddressModesTests(new tcu::TestCaseGroup(testCtx, "address_modes"));
1222 
1223     for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++)
1224     {
1225         const TestCaseConfig &config = testCaseConfigs[configNdx];
1226 
1227         if (!imageViewType.isNormalized() && ((config.u != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE &&
1228                                                config.u != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) ||
1229                                               (config.v != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE &&
1230                                                config.v != VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)))
1231             continue;
1232 
1233         // VK_FORMAT_B4G4R4A4_UNORM_PACK16, VK_FORMAT_B5G6R5_UNORM_PACK16, VK_FORMAT_B5G5R5A1_UNORM_PACK16
1234         // and VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR are forbidden for non-formatless custom border color.
1235         if ((imageFormat == VK_FORMAT_B4G4R4A4_UNORM_PACK16 || imageFormat == VK_FORMAT_B5G6R5_UNORM_PACK16 ||
1236 #ifndef CTS_USES_VULKANSC
1237              imageFormat == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR ||
1238 #endif
1239              imageFormat == VK_FORMAT_B5G5R5A1_UNORM_PACK16) &&
1240             config.border == BORDER_COLOR_CUSTOM && config.customColorFormatless)
1241             continue;
1242 
1243         for (int i = 0; i < 2; ++i)
1244         {
1245             const bool isDSFormat    = isDepthStencilFormat(imageFormat);
1246             const bool sampleStencil = (i > 0);
1247 
1248             if (separateStencilUsage && sampleStencil)
1249                 continue;
1250 
1251             if (!isDSFormat && sampleStencil)
1252                 continue;
1253 
1254             if (isDSFormat)
1255             {
1256                 const auto tcuFormat = mapVkFormat(imageFormat);
1257 
1258                 if (!sampleStencil && !tcu::hasDepthComponent(tcuFormat.order))
1259                     continue;
1260                 if (sampleStencil && !tcu::hasStencilComponent(tcuFormat.order))
1261                     continue;
1262             }
1263 
1264             samplerAddressModesTests->addChild(new SamplerAddressModesTest(
1265                 testCtx,
1266                 getAddressModesCaseName(config.u, config.v, config.w, config.border, config.customColorValueInt,
1267                                         config.customColorFormatless, sampleStencil)
1268                     .c_str(),
1269                 pipelineConstructionType, imageViewType, imageFormat, config.u, config.v, config.w,
1270                 getFormatBorderColor(config.border, imageFormat, sampleStencil),
1271                 getFormatCustomBorderColor(config.customColorValueFloat, config.customColorValueInt, imageFormat,
1272                                            sampleStencil),
1273                 config.customColorFormatless, separateStencilUsage, sampleStencil));
1274         }
1275     }
1276 
1277     return samplerAddressModesTests;
1278 }
1279 
1280 // Exact sampling case:
1281 //    1) Create a texture and a framebuffer image of the same size.
1282 //    2) Draw a full screen quad with the texture and VK_FILTER_NEAREST.
1283 //    3) Verify the rendered image matches the texture exactly.
1284 class ExactSamplingCase : public vkt::TestCase
1285 {
1286 public:
1287     struct Params
1288     {
1289         PipelineConstructionType pipelineConstructionType;
1290         vk::VkFormat format;
1291         bool unnormalizedCoordinates;
1292         bool solidColor;
1293         tcu::Maybe<float> offsetSign; // -1.0 or 1.0
1294     };
1295 
1296     struct PushConstants
1297     {
1298         float texWidth;
1299         float texHeight;
1300     };
1301 
1302     struct VertexData
1303     {
1304         tcu::Vec2 vtxCoords;
1305         tcu::Vec2 texCoords;
1306 
1307         static vk::VkVertexInputBindingDescription getBindingDescription(void);
1308         static std::vector<vk::VkVertexInputAttributeDescription> getAttributeDescriptions(void);
1309     };
1310 
1311     ExactSamplingCase(tcu::TestContext &testCtx, const std::string &name, const Params &params);
~ExactSamplingCase(void)1312     virtual ~ExactSamplingCase(void)
1313     {
1314     }
1315 
1316     virtual void initPrograms(vk::SourceCollections &programCollection) const;
1317     virtual TestInstance *createInstance(Context &context) const;
1318     virtual void checkSupport(Context &context) const;
1319 
1320 private:
1321     Params m_params;
1322 };
1323 
1324 class ExactSamplingInstance : public vkt::TestInstance
1325 {
1326 public:
1327     using Params = ExactSamplingCase::Params;
1328 
1329     ExactSamplingInstance(Context &context, const Params &params);
~ExactSamplingInstance(void)1330     virtual ~ExactSamplingInstance(void)
1331     {
1332     }
1333 
1334     virtual tcu::TestStatus iterate(void);
1335 
1336     vk::VkExtent3D getTextureExtent(void) const;
1337 
1338 private:
1339     Params m_params;
1340 };
1341 
getBindingDescription(void)1342 vk::VkVertexInputBindingDescription ExactSamplingCase::VertexData::getBindingDescription(void)
1343 {
1344     static const vk::VkVertexInputBindingDescription desc = {
1345         0u,                                                           // uint32_t binding;
1346         static_cast<uint32_t>(sizeof(ExactSamplingCase::VertexData)), // uint32_t stride;
1347         vk::VK_VERTEX_INPUT_RATE_VERTEX,                              // VkVertexInputRate inputRate;
1348     };
1349 
1350     return desc;
1351 }
1352 
getAttributeDescriptions(void)1353 std::vector<vk::VkVertexInputAttributeDescription> ExactSamplingCase::VertexData::getAttributeDescriptions(void)
1354 {
1355     static const std::vector<vk::VkVertexInputAttributeDescription> desc = {
1356         {
1357             0u,                                                                        // uint32_t location;
1358             0u,                                                                        // uint32_t binding;
1359             vk::VK_FORMAT_R32G32_SFLOAT,                                               // VkFormat format;
1360             static_cast<uint32_t>(offsetof(ExactSamplingCase::VertexData, vtxCoords)), // uint32_t offset;
1361         },
1362         {
1363             1u,                                                                        // uint32_t location;
1364             0u,                                                                        // uint32_t binding;
1365             vk::VK_FORMAT_R32G32_SFLOAT,                                               // VkFormat format;
1366             static_cast<uint32_t>(offsetof(ExactSamplingCase::VertexData, texCoords)), // uint32_t offset;
1367         },
1368     };
1369 
1370     return desc;
1371 }
1372 
ExactSamplingCase(tcu::TestContext & testCtx,const std::string & name,const Params & params)1373 ExactSamplingCase::ExactSamplingCase(tcu::TestContext &testCtx, const std::string &name, const Params &params)
1374     : vkt::TestCase{testCtx, name}
1375     , m_params(params)
1376 {
1377 }
1378 
initPrograms(vk::SourceCollections & programCollection) const1379 void ExactSamplingCase::initPrograms(vk::SourceCollections &programCollection) const
1380 {
1381     std::ostringstream vertexShader;
1382 
1383     std::string texCoordX = "inTexCoord.x";
1384     std::string texCoordY = "inTexCoord.y";
1385 
1386     if (m_params.unnormalizedCoordinates)
1387     {
1388         texCoordX += " * pushc.texWidth";
1389         texCoordY += " * pushc.texHeight";
1390     }
1391 
1392     vertexShader << "#version 450\n"
1393                  << "\n"
1394                  << "layout(push_constant, std430) uniform PushConstants\n"
1395                  << "{\n"
1396                  << "    float texWidth;\n"
1397                  << "    float texHeight;\n"
1398                  << "} pushc;\n"
1399                  << "\n"
1400                  << "layout(location = 0) in vec2 inPosition;\n"
1401                  << "layout(location = 1) in vec2 inTexCoord;\n"
1402                  << "\n"
1403                  << "layout(location = 0) out vec2 fragTexCoord;\n"
1404                  << "\n"
1405                  << "void main() {\n"
1406                  << "    gl_Position = vec4(inPosition, 0.0, 1.0);\n"
1407                  << "    fragTexCoord = vec2(" << texCoordX << ", " << texCoordY << ");\n"
1408                  << "}\n";
1409 
1410     programCollection.glslSources.add("vert") << glu::VertexSource{vertexShader.str()};
1411 
1412     std::ostringstream fragmentShader;
1413 
1414     std::string typePrefix;
1415     if (vk::isIntFormat(m_params.format))
1416         typePrefix = "i";
1417     else if (vk::isUintFormat(m_params.format))
1418         typePrefix = "u";
1419 
1420     const std::string samplerType = typePrefix + "sampler2D";
1421     const std::string colorType   = typePrefix + "vec4";
1422 
1423     fragmentShader << "#version 450\n"
1424                    << "\n"
1425                    << "layout(set = 0, binding = 0) uniform " << samplerType << " texSampler;\n"
1426                    << "\n"
1427                    << "layout(location = 0) in vec2 fragTexCoord;\n"
1428                    << "\n"
1429                    << "layout(location = 0) out " << colorType << " outColor;\n"
1430                    << "\n"
1431                    << "void main() {\n";
1432 
1433     if (m_params.unnormalizedCoordinates)
1434     {
1435         fragmentShader << "    outColor = textureLod(texSampler, fragTexCoord, 0.0f);";
1436     }
1437     else
1438     {
1439         fragmentShader << "    outColor = texture(texSampler, fragTexCoord);\n";
1440     }
1441 
1442     fragmentShader << "}\n";
1443 
1444     programCollection.glslSources.add("frag") << glu::FragmentSource{fragmentShader.str()};
1445 }
1446 
createInstance(Context & context) const1447 TestInstance *ExactSamplingCase::createInstance(Context &context) const
1448 {
1449     return new ExactSamplingInstance{context, m_params};
1450 }
1451 
checkSupport(Context & context) const1452 void ExactSamplingCase::checkSupport(Context &context) const
1453 {
1454 #ifndef CTS_USES_VULKANSC
1455     if (m_params.format == VK_FORMAT_A8_UNORM_KHR)
1456         context.requireDeviceFunctionality("VK_KHR_maintenance5");
1457 #endif // CTS_USES_VULKANSC
1458 
1459     const auto &vki           = context.getInstanceInterface();
1460     const auto physicalDevice = context.getPhysicalDevice();
1461     const auto props          = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, m_params.format);
1462     const vk::VkFormatFeatureFlags requiredFeatures =
1463         (vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT | vk::VK_FORMAT_FEATURE_TRANSFER_SRC_BIT |
1464          vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT |
1465          (m_params.solidColor ? vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT : 0));
1466 
1467     checkPipelineConstructionRequirements(vki, physicalDevice, m_params.pipelineConstructionType);
1468 
1469     if ((props.optimalTilingFeatures & requiredFeatures) != requiredFeatures)
1470         TCU_THROW(NotSupportedError, "Selected format does not support the required features");
1471 }
1472 
ExactSamplingInstance(Context & context,const Params & params)1473 ExactSamplingInstance::ExactSamplingInstance(Context &context, const Params &params)
1474     : vkt::TestInstance{context}
1475     , m_params(params)
1476 {
1477 }
1478 
getTextureExtent(void) const1479 vk::VkExtent3D ExactSamplingInstance::getTextureExtent(void) const
1480 {
1481     return vk::makeExtent3D(256u, 256u, 1u);
1482 }
1483 
iterate(void)1484 tcu::TestStatus ExactSamplingInstance::iterate(void)
1485 {
1486     const auto &vki       = m_context.getInstanceInterface();
1487     const auto &vkd       = m_context.getDeviceInterface();
1488     const auto physDevice = m_context.getPhysicalDevice();
1489     const auto device     = m_context.getDevice();
1490     auto &allocator       = m_context.getDefaultAllocator();
1491     const auto queue      = m_context.getUniversalQueue();
1492     const auto queueIndex = m_context.getUniversalQueueFamilyIndex();
1493 
1494     const auto tcuFormat  = vk::mapVkFormat(m_params.format);
1495     const auto formatInfo = tcu::getTextureFormatInfo(tcuFormat);
1496     const auto texExtent  = getTextureExtent();
1497     const auto texUsage   = (vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT | vk::VK_IMAGE_USAGE_SAMPLED_BIT);
1498     const auto fbUsage    = (vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
1499     const auto descType   = vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
1500     const auto texLayout  = vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
1501     const bool &unnorm    = m_params.unnormalizedCoordinates;
1502 
1503     // Some code below depends on this.
1504     DE_ASSERT(texExtent.depth == 1u);
1505 
1506     const vk::VkImageCreateInfo texImgCreateInfo = {
1507         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1508         nullptr,                                 // const void* pNext;
1509         0u,                                      // VkImageCreateFlags flags;
1510         vk::VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
1511         m_params.format,                         // VkFormat format;
1512         texExtent,                               // VkExtent3D extent;
1513         1u,                                      // uint32_t mipLevels;
1514         1u,                                      // uint32_t arrayLayers;
1515         vk::VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
1516         vk::VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
1517         texUsage,                                // VkImageUsageFlags usage;
1518         vk::VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
1519         1u,                                      // uint32_t queueFamilyIndexCount;
1520         &queueIndex,                             // const uint32_t* pQueueFamilyIndices;
1521         vk::VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
1522     };
1523 
1524     const vk::VkImageCreateInfo fbImgCreateInfo = {
1525         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1526         nullptr,                                 // const void* pNext;
1527         0u,                                      // VkImageCreateFlags flags;
1528         vk::VK_IMAGE_TYPE_2D,                    // VkImageType imageType;
1529         m_params.format,                         // VkFormat format;
1530         texExtent,                               // VkExtent3D extent;
1531         1u,                                      // uint32_t mipLevels;
1532         1u,                                      // uint32_t arrayLayers;
1533         vk::VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits samples;
1534         vk::VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling tiling;
1535         fbUsage,                                 // VkImageUsageFlags usage;
1536         vk::VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
1537         1u,                                      // uint32_t queueFamilyIndexCount;
1538         &queueIndex,                             // const uint32_t* pQueueFamilyIndices;
1539         vk::VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
1540     };
1541 
1542     // Create main and framebuffer images.
1543     const vk::ImageWithMemory texImage{vkd, device, allocator, texImgCreateInfo, vk::MemoryRequirement::Any};
1544     const vk::ImageWithMemory fbImage{vkd, device, allocator, fbImgCreateInfo, vk::MemoryRequirement::Any};
1545 
1546     // Corresponding image views.
1547     const auto colorSubresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1548     const auto texView = vk::makeImageView(vkd, device, texImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, m_params.format,
1549                                            colorSubresourceRange);
1550     const auto fbView  = vk::makeImageView(vkd, device, fbImage.get(), vk::VK_IMAGE_VIEW_TYPE_2D, m_params.format,
1551                                            colorSubresourceRange);
1552 
1553     // Buffers to create the texture and verify results.
1554     const vk::VkDeviceSize texBufferSize = static_cast<vk::VkDeviceSize>(
1555         static_cast<uint32_t>(tcu::getPixelSize(tcuFormat)) * texExtent.width * texExtent.height * texExtent.depth);
1556     const auto texBufferInfo     = vk::makeBufferCreateInfo(texBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
1557     const auto resultsBufferInfo = vk::makeBufferCreateInfo(texBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1558     const vk::BufferWithMemory texBuffer{vkd, device, allocator, texBufferInfo, vk::MemoryRequirement::HostVisible};
1559     const vk::BufferWithMemory resultsBuffer{vkd, device, allocator, resultsBufferInfo,
1560                                              vk::MemoryRequirement::HostVisible};
1561 
1562     // Create texture.
1563     const tcu::IVec2 iImgSize{static_cast<int>(texExtent.width), static_cast<int>(texExtent.height)};
1564     auto &texBufferAlloc = texBuffer.getAllocation();
1565     auto texBufferPtr    = reinterpret_cast<char *>(texBufferAlloc.getHostPtr()) + texBufferAlloc.getOffset();
1566     const tcu::PixelBufferAccess texPixels{tcuFormat, iImgSize[0], iImgSize[1], 1, texBufferPtr};
1567 
1568     const int W = texPixels.getWidth();
1569     const int H = texPixels.getHeight();
1570     const int D = texPixels.getDepth();
1571 
1572     const float divX = static_cast<float>(W - 1);
1573     const float divY = static_cast<float>(H - 1);
1574 
1575     tcu::Vec4 texColor;
1576 
1577     for (int x = 0; x < W; ++x)
1578         for (int y = 0; y < H; ++y)
1579             for (int z = 0; z < D; ++z)
1580             {
1581                 if (m_params.solidColor)
1582                 {
1583                     // Texture with solid color for filtered sampling.
1584                     texColor = tcu::Vec4{0.5f, 0.25f, 0.7529411764705882f, 1.0f};
1585                 }
1586                 else
1587                 {
1588                     // Use a color gradient otherwise.
1589                     const float colorX = static_cast<float>(x) / divX;
1590                     const float colorY = static_cast<float>(y) / divY;
1591                     const float colorZ = std::min(colorX, colorY);
1592 
1593                     texColor = tcu::Vec4{colorX, colorY, colorZ, 1.0f};
1594                 }
1595                 const tcu::Vec4 finalColor = (texColor - formatInfo.lookupBias) / formatInfo.lookupScale;
1596                 texPixels.setPixel(finalColor, x, y, z);
1597             }
1598 
1599     vk::flushAlloc(vkd, device, texBufferAlloc);
1600 
1601     float minU = 0.0f;
1602     float maxU = 1.0f;
1603     float minV = 0.0f;
1604     float maxV = 1.0f;
1605 
1606     // When testing the edges, apply a texture offset of almost half a texel, so the sample location is very close to the texel border.
1607     // Note that the spec only requires precision of about 1e-05, and texExtent.width can be 256
1608     if (m_params.offsetSign)
1609     {
1610         const float sign = m_params.offsetSign.get();
1611         DE_ASSERT(sign == 1.0f || sign == -1.0f);
1612         const float offsetWidth  = 0.498f / static_cast<float>(texExtent.width);
1613         const float offsetHeight = 0.498f / static_cast<float>(texExtent.height);
1614 
1615         minU += sign * offsetWidth;
1616         maxU += sign * offsetWidth;
1617         minV += sign * offsetHeight;
1618         maxV += sign * offsetHeight;
1619     }
1620 
1621     const std::vector<ExactSamplingCase::VertexData> fullScreenQuad = {
1622         {
1623             {1.f, -1.f},
1624             {maxU, minV},
1625         },
1626         {
1627             {-1.f, -1.f},
1628             {minU, minV},
1629         },
1630         {
1631             {-1.f, 1.f},
1632             {minU, maxV},
1633         },
1634         {
1635             {-1.f, 1.f},
1636             {minU, maxV},
1637         },
1638         {
1639             {1.f, -1.f},
1640             {maxU, minV},
1641         },
1642         {
1643             {1.f, 1.f},
1644             {maxU, maxV},
1645         },
1646     };
1647 
1648     // Vertex buffer.
1649     const vk::VkDeviceSize vertexBufferSize =
1650         static_cast<vk::VkDeviceSize>(fullScreenQuad.size() * sizeof(decltype(fullScreenQuad)::value_type));
1651     const auto vertexBufferInfo = vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1652     const vk::BufferWithMemory vertexBuffer{vkd, device, allocator, vertexBufferInfo,
1653                                             vk::MemoryRequirement::HostVisible};
1654 
1655     // Copy data to vertex buffer.
1656     const auto &vertexAlloc  = vertexBuffer.getAllocation();
1657     const auto vertexDataPtr = reinterpret_cast<char *>(vertexAlloc.getHostPtr()) + vertexAlloc.getOffset();
1658     deMemcpy(vertexDataPtr, fullScreenQuad.data(), static_cast<size_t>(vertexBufferSize));
1659     vk::flushAlloc(vkd, device, vertexAlloc);
1660 
1661     // Descriptor set layout.
1662     vk::DescriptorSetLayoutBuilder layoutBuilder;
1663     layoutBuilder.addSingleBinding(descType, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1664     const auto descriptorSetLayout = layoutBuilder.build(vkd, device);
1665 
1666     // Descriptor pool.
1667     vk::DescriptorPoolBuilder poolBuilder;
1668     poolBuilder.addType(descType);
1669     const auto descriptorPool =
1670         poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1671 
1672     // Descriptor set.
1673     const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
1674 
1675     // Texture sampler. When using a solid color, test linear filtering. Linear filtering may incur in a small precission loss, but
1676     // it should be minimal and we should get the same color when converting back to the original format.
1677     const auto minMagFilter = (m_params.solidColor ? vk::VK_FILTER_LINEAR : vk::VK_FILTER_NEAREST);
1678     const auto addressMode  = (unnorm ? vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : vk::VK_SAMPLER_ADDRESS_MODE_REPEAT);
1679     const auto unnormalizedCoordinates = (unnorm ? VK_TRUE : VK_FALSE);
1680 
1681     const vk::VkSamplerCreateInfo samplerCreateInfo = {
1682         vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,   // VkStructureType sType;
1683         nullptr,                                     // const void* pNext;
1684         0u,                                          // VkSamplerCreateFlags flags;
1685         minMagFilter,                                // VkFilter magFilter;
1686         minMagFilter,                                // VkFilter minFilter;
1687         vk::VK_SAMPLER_MIPMAP_MODE_NEAREST,          // VkSamplerMipmapMode mipmapMode;
1688         addressMode,                                 // VkSamplerAddressMode addressModeU;
1689         addressMode,                                 // VkSamplerAddressMode addressModeV;
1690         addressMode,                                 // VkSamplerAddressMode addressModeW;
1691         0.0f,                                        // float mipLodBias;
1692         VK_FALSE,                                    // VkBool32 anisotropyEnable;
1693         1.0f,                                        // float maxAnisotropy;
1694         VK_FALSE,                                    // VkBool32 compareEnable;
1695         vk::VK_COMPARE_OP_NEVER,                     // VkCompareOp compareOp;
1696         0.0f,                                        // float minLod;
1697         0.0f,                                        // float maxLod;
1698         vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
1699         unnormalizedCoordinates,                     // VkBool32 unnormalizedCoordinates;
1700     };
1701     const auto texSampler = vk::createSampler(vkd, device, &samplerCreateInfo);
1702 
1703     // Update descriptor set with the descriptor.
1704     vk::DescriptorSetUpdateBuilder updateBuilder;
1705     const auto descriptorImageInfo = vk::makeDescriptorImageInfo(texSampler.get(), texView.get(), texLayout);
1706     updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), descType,
1707                               &descriptorImageInfo);
1708     updateBuilder.update(vkd, device);
1709 
1710     // Shader modules.
1711     const auto vertexModule = vk::ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
1712     const auto fragModule   = vk::ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
1713 
1714     // Render pass.
1715     const vk::VkAttachmentDescription fbAttachment = {
1716         0u,                                           // VkAttachmentDescriptionFlags flags;
1717         m_params.format,                              // VkFormat format;
1718         vk::VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits samples;
1719         vk::VK_ATTACHMENT_LOAD_OP_CLEAR,              // VkAttachmentLoadOp loadOp;
1720         vk::VK_ATTACHMENT_STORE_OP_STORE,             // VkAttachmentStoreOp storeOp;
1721         vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp stencilLoadOp;
1722         vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp stencilStoreOp;
1723         vk::VK_IMAGE_LAYOUT_UNDEFINED,                // VkImageLayout initialLayout;
1724         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
1725     };
1726 
1727     const vk::VkAttachmentReference colorRef = {
1728         0u,                                           // uint32_t attachment;
1729         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
1730     };
1731 
1732     const vk::VkSubpassDescription subpass = {
1733         0u,                                  // VkSubpassDescriptionFlags flags;
1734         vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
1735         0u,                                  // uint32_t inputAttachmentCount;
1736         nullptr,                             // const VkAttachmentReference* pInputAttachments;
1737         1u,                                  // uint32_t colorAttachmentCount;
1738         &colorRef,                           // const VkAttachmentReference* pColorAttachments;
1739         0u,                                  // const VkAttachmentReference* pResolveAttachments;
1740         nullptr,                             // const VkAttachmentReference* pDepthStencilAttachment;
1741         0u,                                  // uint32_t preserveAttachmentCount;
1742         nullptr,                             // const uint32_t* pPreserveAttachments;
1743     };
1744 
1745     const vk::VkRenderPassCreateInfo renderPassInfo = {
1746         vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1747         nullptr,                                       // const void* pNext;
1748         0u,                                            // VkRenderPassCreateFlags flags;
1749         1u,                                            // uint32_t attachmentCount;
1750         &fbAttachment,                                 // const VkAttachmentDescription* pAttachments;
1751         1u,                                            // uint32_t subpassCount;
1752         &subpass,                                      // const VkSubpassDescription* pSubpasses;
1753         0u,                                            // uint32_t dependencyCount;
1754         nullptr,                                       // const VkSubpassDependency* pDependencies;
1755     };
1756     RenderPassWrapper renderPass(m_params.pipelineConstructionType, vkd, device, &renderPassInfo);
1757 
1758     // Framebuffer.
1759     std::vector<vk::VkImageView> attachments;
1760     attachments.push_back(fbView.get());
1761     renderPass.createFramebuffer(vkd, device, 1u, &fbImage.get(), &fbView.get(), texExtent.width, texExtent.height,
1762                                  texExtent.depth);
1763 
1764     // Push constant range.
1765     const vk::VkPushConstantRange pcRange = {
1766         vk::VK_SHADER_STAGE_VERTEX_BIT,                                  // VkShaderStageFlags stageFlags;
1767         0u,                                                              // uint32_t offset;
1768         static_cast<uint32_t>(sizeof(ExactSamplingCase::PushConstants)), // uint32_t size;
1769     };
1770 
1771     // Pipeline layout.
1772     const vk::VkPipelineLayoutCreateInfo pipelineLayoutInfo = {
1773         vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1774         nullptr,                                           // const void* pNext;
1775         0u,                                                // VkPipelineLayoutCreateFlags flags;
1776         1u,                                                // uint32_t setLayoutCount;
1777         &descriptorSetLayout.get(),                        // const VkDescriptorSetLayout* pSetLayouts;
1778         1u,                                                // uint32_t pushConstantRangeCount;
1779         &pcRange,                                          // const VkPushConstantRange* pPushConstantRanges;
1780     };
1781     const vk::PipelineLayoutWrapper pipelineLayout(m_params.pipelineConstructionType, vkd, device, &pipelineLayoutInfo);
1782 
1783     // Graphics pipeline.
1784     const std::vector<vk::VkViewport> viewports{vk::makeViewport(texExtent)};
1785     const vk::VkRect2D renderArea = vk::makeRect2D(texExtent);
1786     const std::vector<vk::VkRect2D> scissors{renderArea};
1787 
1788     const auto vtxBindingDescription    = ExactSamplingCase::VertexData::getBindingDescription();
1789     const auto vtxAttributeDescriptions = ExactSamplingCase::VertexData::getAttributeDescriptions();
1790 
1791     const vk::VkPipelineVertexInputStateCreateInfo vertexInputInfo = {
1792         vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType                             sType
1793         nullptr,                // const void*                                 pNext
1794         0u,                     // VkPipelineVertexInputStateCreateFlags       flags
1795         1u,                     // uint32_t                                    vertexBindingDescriptionCount
1796         &vtxBindingDescription, // const VkVertexInputBindingDescription*      pVertexBindingDescriptions
1797         static_cast<uint32_t>(
1798             vtxAttributeDescriptions
1799                 .size()),                // uint32_t                                    vertexAttributeDescriptionCount
1800         vtxAttributeDescriptions.data(), // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
1801     };
1802 
1803     GraphicsPipelineWrapper pipeline(vki, vkd, physDevice, device, m_context.getDeviceExtensions(),
1804                                      m_params.pipelineConstructionType);
1805     pipeline.setDefaultDepthStencilState()
1806         .setDefaultRasterizationState()
1807         .setDefaultMultisampleState()
1808         .setDefaultColorBlendState()
1809         .setupVertexInputState(&vertexInputInfo)
1810         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertexModule)
1811         .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule)
1812         .setupFragmentOutputState(*renderPass)
1813         .setMonolithicPipelineLayout(pipelineLayout)
1814         .buildPipeline();
1815 
1816     // Command pool and command buffer.
1817     const auto cmdPool =
1818         vk::createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueIndex);
1819     const auto cmdBufferPtr =
1820         vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1821     const auto cmdBuffer = cmdBufferPtr.get();
1822 
1823     // Draw quad.
1824     const ExactSamplingCase::PushConstants pushConstants = {
1825         static_cast<float>(texExtent.width),
1826         static_cast<float>(texExtent.height),
1827     };
1828 
1829     const tcu::Vec4 clearFbColor(0.0f, 0.0f, 0.0f, 1.0f);
1830     const vk::VkDeviceSize vertexBufferOffset = 0ull;
1831 
1832     const auto vertexBufferBarrier =
1833         vk::makeBufferMemoryBarrier(vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
1834                                     vertexBuffer.get(), 0ull, vertexBufferSize);
1835     const auto preBufferCopyBarrier = vk::makeBufferMemoryBarrier(
1836         vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, texBuffer.get(), 0ull, texBufferSize);
1837     const auto preTexCopyBarrier =
1838         vk::makeImageMemoryBarrier(0u, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED,
1839                                    vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texImage.get(), colorSubresourceRange);
1840     const auto postTexCopyBarrier = vk::makeImageMemoryBarrier(
1841         vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1842         texLayout, texImage.get(), colorSubresourceRange);
1843     const auto texCopyRange = vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1844     const auto texImageCopy = vk::makeBufferImageCopy(texExtent, texCopyRange);
1845 
1846     vk::beginCommandBuffer(vkd, cmdBuffer);
1847 
1848     vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u, 0u,
1849                            nullptr, 1u, &vertexBufferBarrier, 0u, nullptr);
1850     vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
1851                            nullptr, 1u, &preBufferCopyBarrier, 0u, nullptr);
1852     vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
1853                            nullptr, 0u, nullptr, 1u, &preTexCopyBarrier);
1854     vkd.cmdCopyBufferToImage(cmdBuffer, texBuffer.get(), texImage.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u,
1855                              &texImageCopy);
1856     vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
1857                            0u, nullptr, 0u, nullptr, 1u, &postTexCopyBarrier);
1858 
1859     renderPass.begin(vkd, cmdBuffer, renderArea, clearFbColor);
1860     pipeline.bind(cmdBuffer);
1861     vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u,
1862                               &descriptorSet.get(), 0u, nullptr);
1863     vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1864     vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), vk::VK_SHADER_STAGE_VERTEX_BIT, 0u,
1865                          static_cast<uint32_t>(sizeof(pushConstants)), &pushConstants);
1866     vkd.cmdDraw(cmdBuffer, static_cast<uint32_t>(fullScreenQuad.size()), 1u, 0u, 0u);
1867     renderPass.end(vkd, cmdBuffer);
1868 
1869     vk::copyImageToBuffer(vkd, cmdBuffer, fbImage.get(), resultsBuffer.get(), iImgSize);
1870 
1871     vk::endCommandBuffer(vkd, cmdBuffer);
1872     vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1873 
1874     // Check results.
1875     const auto &resultsBufferAlloc = resultsBuffer.getAllocation();
1876     vk::invalidateAlloc(vkd, device, resultsBufferAlloc);
1877 
1878     const auto resultsBufferPtr =
1879         reinterpret_cast<const char *>(resultsBufferAlloc.getHostPtr()) + resultsBufferAlloc.getOffset();
1880     const tcu::ConstPixelBufferAccess resultPixels{tcuFormat, iImgSize[0], iImgSize[1], 1, resultsBufferPtr};
1881 
1882     const tcu::TextureFormat diffFormat{tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8};
1883     const auto diffBytes = tcu::getPixelSize(diffFormat) * iImgSize[0] * iImgSize[1];
1884     std::unique_ptr<uint8_t[]> diffData{new uint8_t[diffBytes]};
1885     const tcu::PixelBufferAccess diffImg{diffFormat, iImgSize[0], iImgSize[1], 1, diffData.get()};
1886 
1887     const tcu::Vec4 colorRed{1.0f, 0.0f, 0.0f, 1.0f};
1888     const tcu::Vec4 colorGreen{0.0f, 1.0f, 0.0f, 1.0f};
1889 
1890     // Clear diff image.
1891     deMemset(diffData.get(), 0, static_cast<size_t>(diffBytes));
1892 
1893     bool pass = true;
1894     for (int x = 0; x < W; ++x)
1895         for (int y = 0; y < H; ++y)
1896             for (int z = 0; z < D; ++z)
1897             {
1898                 const auto inPix  = texPixels.getPixel(x, y, z);
1899                 const auto outPix = resultPixels.getPixel(x, y, z);
1900                 if (inPix == outPix)
1901                 {
1902                     diffImg.setPixel(colorGreen, x, y, z);
1903                 }
1904                 else
1905                 {
1906                     pass = false;
1907                     diffImg.setPixel(colorRed, x, y, z);
1908                 }
1909             }
1910 
1911     tcu::TestStatus status = tcu::TestStatus::pass("Pass");
1912     if (!pass)
1913     {
1914         auto &log = m_context.getTestContext().getLog();
1915         log << tcu::TestLog::Image("input", "Input texture", texPixels);
1916         log << tcu::TestLog::Image("output", "Rendered image", resultPixels);
1917         log << tcu::TestLog::Image("diff", "Mismatched pixels in red", diffImg);
1918         status = tcu::TestStatus::fail("Pixel mismatch; please check the rendered image");
1919     }
1920 
1921     return status;
1922 }
1923 
1924 enum class LodBiasCase
1925 {
1926     SAMPLER_BIAS   = 0,
1927     SAMPLER_MINLOD = 1,
1928     SHADER_LOD     = 2,
1929     SHADER_BIAS    = 3,
1930     VIEW_MINLOD    = 4,
1931     CASE_COUNT     = 5,
1932 };
1933 
getLodBiasCaseName(LodBiasCase lodBiasCase)1934 std::string getLodBiasCaseName(LodBiasCase lodBiasCase)
1935 {
1936     std::string name;
1937 
1938     switch (lodBiasCase)
1939     {
1940     case LodBiasCase::SAMPLER_BIAS:
1941         name = "sampler_bias";
1942         break;
1943     case LodBiasCase::SAMPLER_MINLOD:
1944         name = "sampler_minlod";
1945         break;
1946     case LodBiasCase::SHADER_LOD:
1947         name = "shader_lod";
1948         break;
1949     case LodBiasCase::SHADER_BIAS:
1950         name = "shader_bias";
1951         break;
1952     case LodBiasCase::VIEW_MINLOD:
1953         name = "view_minlod";
1954         break;
1955     case LodBiasCase::CASE_COUNT: // fallthrough
1956     default:
1957         DE_ASSERT(false);
1958         break;
1959     }
1960 
1961     return name;
1962 }
1963 
1964 struct MaxSamplerLodBiasParams
1965 {
1966     const PipelineConstructionType pipelineConstructionType;
1967     const LodBiasCase lodBiasCase;
1968 };
1969 
1970 class MaxSamplerLodBiasCase : public vkt::TestCase
1971 {
1972 public:
MaxSamplerLodBiasCase(tcu::TestContext & testCtx,const std::string & name,const MaxSamplerLodBiasParams & params)1973     MaxSamplerLodBiasCase(tcu::TestContext &testCtx, const std::string &name, const MaxSamplerLodBiasParams &params)
1974         : vkt::TestCase(testCtx, name)
1975         , m_params(params)
1976     {
1977     }
~MaxSamplerLodBiasCase(void)1978     virtual ~MaxSamplerLodBiasCase(void)
1979     {
1980     }
1981 
1982     void checkSupport(Context &context) const override;
1983     void initPrograms(vk::SourceCollections &programCollection) const override;
1984     TestInstance *createInstance(Context &context) const override;
1985 
1986 protected:
1987     const MaxSamplerLodBiasParams m_params;
1988 };
1989 
1990 class MaxSamplerLodBiasInstance : public vkt::TestInstance
1991 {
1992 public:
MaxSamplerLodBiasInstance(Context & context,const MaxSamplerLodBiasParams & params)1993     MaxSamplerLodBiasInstance(Context &context, const MaxSamplerLodBiasParams &params)
1994         : vkt::TestInstance(context)
1995         , m_params(params)
1996     {
1997     }
~MaxSamplerLodBiasInstance(void)1998     virtual ~MaxSamplerLodBiasInstance(void)
1999     {
2000     }
2001 
2002     tcu::TestStatus iterate(void);
2003 
2004 protected:
2005     const MaxSamplerLodBiasParams m_params;
2006 };
2007 
checkSupport(Context & context) const2008 void MaxSamplerLodBiasCase::checkSupport(Context &context) const
2009 {
2010     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
2011                                           m_params.pipelineConstructionType);
2012 
2013     if (m_params.lodBiasCase == LodBiasCase::VIEW_MINLOD)
2014         context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2015 }
2016 
initPrograms(vk::SourceCollections & programCollection) const2017 void MaxSamplerLodBiasCase::initPrograms(vk::SourceCollections &programCollection) const
2018 {
2019     std::ostringstream vert;
2020     vert << "#version 460\n"
2021          << "layout (location=0) in vec4 inPos;\n"
2022          << "void main (void) {\n"
2023          << "    gl_Position = inPos;\n"
2024          << "}\n";
2025     programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
2026 
2027     std::string sampleStatement;
2028     const std::string sampleCoords = "vec2(gl_FragCoord.x / pc.fbWidth, gl_FragCoord.y / pc.fbHeight)";
2029 
2030     if (m_params.lodBiasCase == LodBiasCase::SHADER_LOD)
2031         sampleStatement = "textureLod(texSampler, " + sampleCoords + ", pc.lodLevel)";
2032     else if (m_params.lodBiasCase == LodBiasCase::SHADER_BIAS)
2033         sampleStatement = "texture(texSampler, " + sampleCoords + ", pc.lodLevel)";
2034     else
2035         sampleStatement = "textureLod(texSampler, " + sampleCoords + ", 0.0)";
2036 
2037     DE_ASSERT(!sampleStatement.empty());
2038 
2039     std::ostringstream frag;
2040     frag << "#version 460\n"
2041          << "layout (location=0) out vec4 outColor;\n"
2042          << "layout (set=0, binding=0) uniform sampler2D texSampler;\n"
2043          << "layout (push_constant, std430) uniform PushConstantBlock {\n"
2044          << "    float lodLevel;\n"
2045          << "    float fbWidth;\n"
2046          << "    float fbHeight;\n"
2047          << "} pc;\n"
2048          << "void main (void) {\n"
2049          << "    outColor = " << sampleStatement << ";\n"
2050          << "}\n";
2051     programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
2052 }
2053 
createInstance(Context & context) const2054 TestInstance *MaxSamplerLodBiasCase::createInstance(Context &context) const
2055 {
2056     return new MaxSamplerLodBiasInstance(context, m_params);
2057 }
2058 
iterate(void)2059 tcu::TestStatus MaxSamplerLodBiasInstance::iterate(void)
2060 {
2061     const auto ctx               = m_context.getContextCommonData();
2062     const auto vkFormat          = VK_FORMAT_R8G8B8A8_UNORM;
2063     const auto tcuFormat         = mapVkFormat(vkFormat);
2064     const auto imageType         = VK_IMAGE_TYPE_2D;
2065     const auto tiling            = VK_IMAGE_TILING_OPTIMAL;
2066     const auto textureUsage      = (VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
2067     const auto fbUsage           = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
2068     const auto sampleCount       = VK_SAMPLE_COUNT_1_BIT;
2069     const auto descriptorType    = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
2070     const auto maxLodBias        = getPhysicalDeviceProperties(ctx.vki, ctx.physicalDevice).limits.maxSamplerLodBias;
2071     const auto roundedBias       = deFloatFloor(maxLodBias + 0.5f);
2072     const auto textureProperties = getPhysicalDeviceImageFormatProperties(ctx.vki, ctx.physicalDevice, vkFormat,
2073                                                                           imageType, tiling, textureUsage, 0u);
2074     const auto textureExtent     = makeExtent3D(textureProperties.maxExtent.width, 1u, 1u);
2075     const auto fbExtent          = tcu::IVec3(1, 1, 1);
2076     const auto vkExtent          = makeExtent3D(fbExtent);
2077     const auto baseSeed          = 1687852938u;
2078 
2079     const VkImageCreateInfo textureCreateInfo = {
2080         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
2081         nullptr,                             // const void* pNext;
2082         0u,                                  // VkImageCreateFlags flags;
2083         imageType,                           // VkImageType imageType;
2084         vkFormat,                            // VkFormat format;
2085         textureExtent,                       // VkExtent3D extent;
2086         textureProperties.maxMipLevels,      // uint32_t mipLevels;
2087         1u,                                  // uint32_t arrayLayers;
2088         sampleCount,                         // VkSampleCountFlagBits samples;
2089         tiling,                              // VkImageTiling tiling;
2090         textureUsage,                        // VkImageUsageFlags usage;
2091         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
2092         0u,                                  // uint32_t queueFamilyIndexCount;
2093         nullptr,                             // const uint32_t* pQueueFamilyIndices;
2094         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
2095     };
2096     ImageWithMemory texture(ctx.vkd, ctx.device, ctx.allocator, textureCreateInfo, MemoryRequirement::Any);
2097     const auto textureColorSRR =
2098         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, textureCreateInfo.mipLevels, 0u, 1u);
2099     const auto accessedLevel = std::min(roundedBias, static_cast<float>(textureCreateInfo.mipLevels - 1u));
2100 
2101 #ifndef CTS_USES_VULKANSC
2102     std::unique_ptr<VkImageViewMinLodCreateInfoEXT> viewMinLodPtr;
2103     if (m_params.lodBiasCase == LodBiasCase::VIEW_MINLOD)
2104     {
2105         viewMinLodPtr.reset(new VkImageViewMinLodCreateInfoEXT{
2106             VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT, nullptr,
2107             accessedLevel, // VUID-VkImageViewMinLodCreateInfoEXT-minLod-06456 prevents us from using maxLodBias directly.
2108         });
2109     }
2110 #endif // CTS_USES_VULKANSC
2111 
2112     const VkImageViewCreateInfo viewCreateInfo = {
2113         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
2114 #ifndef CTS_USES_VULKANSC
2115         viewMinLodPtr.get(), // const void* pNext;
2116 #else
2117         nullptr, // const void* pNext;
2118 #endif                         // CTS_USES_VULKANSC
2119         0u,                    // VkImageViewCreateFlags flags;
2120         texture.get(),         // VkImage image;
2121         VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
2122         vkFormat,              // VkFormat format;
2123         {
2124             // VkComponentMapping components;
2125             VK_COMPONENT_SWIZZLE_R,
2126             VK_COMPONENT_SWIZZLE_G,
2127             VK_COMPONENT_SWIZZLE_B,
2128             VK_COMPONENT_SWIZZLE_A,
2129         },
2130         textureColorSRR, // VkImageSubresourceRange subresourceRange;
2131     };
2132     const auto textureView = createImageView(ctx.vkd, ctx.device, &viewCreateInfo);
2133 
2134     // Output color buffer.
2135     ImageWithBuffer colorBuffer(ctx.vkd, ctx.device, ctx.allocator, vkExtent, vkFormat, fbUsage, imageType);
2136 
2137     // Texture sampler.
2138     const float samplerMipLodBias = ((m_params.lodBiasCase == LodBiasCase::SAMPLER_BIAS) ? maxLodBias : 0.0f);
2139     const float samplerMinLod     = ((m_params.lodBiasCase == LodBiasCase::SAMPLER_MINLOD) ? maxLodBias : 0.0f);
2140     const VkSamplerCreateInfo samplerCreateInfo = {
2141         VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,   // VkStructureType sType;
2142         nullptr,                                 // const void* pNext;
2143         0u,                                      // VkSamplerCreateFlags flags;
2144         VK_FILTER_NEAREST,                       // VkFilter magFilter;
2145         VK_FILTER_NEAREST,                       // VkFilter minFilter;
2146         VK_SAMPLER_MIPMAP_MODE_NEAREST,          // VkSamplerMipmapMode mipmapMode;
2147         VK_SAMPLER_ADDRESS_MODE_REPEAT,          // VkSamplerAddressMode addressModeU;
2148         VK_SAMPLER_ADDRESS_MODE_REPEAT,          // VkSamplerAddressMode addressModeV;
2149         VK_SAMPLER_ADDRESS_MODE_REPEAT,          // VkSamplerAddressMode addressModeW;
2150         samplerMipLodBias,                       // float mipLodBias;
2151         VK_FALSE,                                // VkBool32 anisotropyEnable;
2152         0.0f,                                    // float maxAnisotropy;
2153         VK_FALSE,                                // VkBool32 compareEnable;
2154         VK_COMPARE_OP_NEVER,                     // VkCompareOp compareOp;
2155         samplerMinLod,                           // float minLod;
2156         VK_LOD_CLAMP_NONE,                       // float maxLod;
2157         VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
2158         VK_FALSE,                                // VkBool32 unnormalizedCoordinates;
2159     };
2160     const auto sampler = createSampler(ctx.vkd, ctx.device, &samplerCreateInfo);
2161 
2162     // Vertex buffer.
2163     const std::vector<tcu::Vec4> vertices{
2164         tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
2165         tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f),
2166         tcu::Vec4(1.0f, -1.0f, 0.0f, 1.0f),
2167         tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f),
2168     };
2169     const auto vertexBufferSize = static_cast<VkDeviceSize>(de::dataSize(vertices));
2170     const auto vertexBufferInfo = makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
2171     BufferWithMemory vertexBuffer(ctx.vkd, ctx.device, ctx.allocator, vertexBufferInfo, MemoryRequirement::HostVisible);
2172     auto &vertexBufferAlloc       = vertexBuffer.getAllocation();
2173     void *vertexBufferDataPtr     = vertexBufferAlloc.getHostPtr();
2174     const auto vertexBufferOffset = static_cast<VkDeviceSize>(0);
2175 
2176     deMemcpy(vertexBufferDataPtr, de::dataOrNull(vertices), de::dataSize(vertices));
2177     flushAlloc(ctx.vkd, ctx.device, vertexBufferAlloc);
2178 
2179     // Render pass and framebuffer.
2180     auto renderPass = RenderPassWrapper(m_params.pipelineConstructionType, ctx.vkd, ctx.device, vkFormat);
2181     renderPass.createFramebuffer(ctx.vkd, ctx.device, colorBuffer.getImage(), colorBuffer.getImageView(),
2182                                  vkExtent.width, vkExtent.height);
2183 
2184     // Push constants.
2185     const std::vector<float> pcValues{maxLodBias, static_cast<float>(vkExtent.width),
2186                                       static_cast<float>(vkExtent.height)};
2187     const auto pcSize   = static_cast<uint32_t>(de::dataSize(pcValues));
2188     const auto pcStages = VK_SHADER_STAGE_FRAGMENT_BIT;
2189     const auto pcRange  = makePushConstantRange(pcStages, 0u, pcSize);
2190 
2191     // Descriptor pool and set.
2192     DescriptorSetLayoutBuilder setLayoutBuilder;
2193     setLayoutBuilder.addSingleBinding(descriptorType, VK_SHADER_STAGE_FRAGMENT_BIT);
2194     const auto descriptorSetLayout = setLayoutBuilder.build(ctx.vkd, ctx.device);
2195     const PipelineLayoutWrapper pipelineLayout(m_params.pipelineConstructionType, ctx.vkd, ctx.device,
2196                                                *descriptorSetLayout, &pcRange);
2197 
2198     DescriptorPoolBuilder descriptorPoolBuilder;
2199     descriptorPoolBuilder.addType(descriptorType);
2200     const auto descriptorPool =
2201         descriptorPoolBuilder.build(ctx.vkd, ctx.device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2202     const auto descriptorSet = makeDescriptorSet(ctx.vkd, ctx.device, *descriptorPool, *descriptorSetLayout);
2203 
2204     DescriptorSetUpdateBuilder setUpdateBuilder;
2205     const auto samplerDescriptorInfo =
2206         makeDescriptorImageInfo(*sampler, *textureView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2207     setUpdateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
2208                                  &samplerDescriptorInfo);
2209     setUpdateBuilder.update(ctx.vkd, ctx.device);
2210 
2211     // Pipeline.
2212     const auto &binaries = m_context.getBinaryCollection();
2213     const auto vertMod   = ShaderWrapper(ctx.vkd, ctx.device, binaries.get("vert"));
2214     const auto fragMod   = ShaderWrapper(ctx.vkd, ctx.device, binaries.get("frag"));
2215 
2216     const std::vector<VkViewport> viewports(1u, makeViewport(vkExtent));
2217     const std::vector<VkRect2D> scissors(1u, makeRect2D(vkExtent));
2218 
2219     GraphicsPipelineWrapper pipeline(ctx.vki, ctx.vkd, ctx.physicalDevice, ctx.device, m_context.getDeviceExtensions(),
2220                                      m_params.pipelineConstructionType);
2221     pipeline.setDefaultDepthStencilState()
2222         .setDefaultRasterizationState()
2223         .setDefaultMultisampleState()
2224         .setDefaultColorBlendState()
2225         .setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
2226         .setupVertexInputState()
2227         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertMod)
2228         .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragMod)
2229         .setupFragmentOutputState(*renderPass)
2230         .setMonolithicPipelineLayout(pipelineLayout)
2231         .buildPipeline();
2232 
2233     CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
2234     const auto cmdBuffer = *cmd.cmdBuffer;
2235 
2236     beginCommandBuffer(ctx.vkd, cmdBuffer);
2237 
2238     // Transition texture to layout suitable for filling.
2239     const auto preFillBarrier =
2240         makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2241                                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture.get(), textureColorSRR);
2242     cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2243                                   &preFillBarrier);
2244 
2245     // Fill every level with a different random color.
2246     auto &log = m_context.getTestContext().getLog();
2247     de::Random rnd(baseSeed + static_cast<uint32_t>(m_params.lodBiasCase));
2248     std::vector<tcu::Vec4> levelColors;
2249     levelColors.reserve(textureCreateInfo.mipLevels);
2250 
2251     for (uint32_t level = 0u; level < textureCreateInfo.mipLevels; ++level)
2252     {
2253         const auto levelRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, level, 1u, 0u, 1u);
2254         // If we "embed" these expressions in the constructor below, separated by commas, the order in which colors are obtained would depend on the compiler.
2255         const auto red   = rnd.getFloat(0.0f, 1.0f);
2256         const auto green = rnd.getFloat(0.0f, 1.0f);
2257         const auto blue  = rnd.getFloat(0.0f, 1.0f);
2258         const tcu::Vec4 clearValue(red, green, blue, 1.0f);
2259         const auto clearValueColor = makeClearValueColorVec4(clearValue);
2260 
2261         levelColors.push_back(clearValue);
2262         ctx.vkd.cmdClearColorImage(cmdBuffer, texture.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2263                                    &clearValueColor.color, 1u, &levelRange);
2264         log << tcu::TestLog::Message << "Level " << level << " cleared to " << clearValue << tcu::TestLog::EndMessage;
2265     }
2266 
2267     // Transition texture to suitable layout for reading it in the shader.
2268     const auto preReadBarrier = makeImageMemoryBarrier(
2269         VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2270         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, texture.get(), textureColorSRR);
2271     cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
2272                                   VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, &preReadBarrier);
2273 
2274     const tcu::Vec4 fbClearColor(0.0f, 0.0f, 0.0f, 0.0f);
2275     renderPass.begin(ctx.vkd, cmdBuffer, scissors.at(0u), fbClearColor);
2276     ctx.vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2277     pipeline.bind(cmdBuffer);
2278     ctx.vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
2279                                   &descriptorSet.get(), 0u, nullptr);
2280     ctx.vkd.cmdPushConstants(cmdBuffer, *pipelineLayout, pcStages, 0u, pcSize, de::dataOrNull(pcValues));
2281     ctx.vkd.cmdDraw(cmdBuffer, de::sizeU32(vertices), 1u, 0u, 0u);
2282     renderPass.end(ctx.vkd, cmdBuffer);
2283 
2284     // Copy color buffer to verification buffer.
2285     copyImageToBuffer(ctx.vkd, cmdBuffer, colorBuffer.getImage(), colorBuffer.getBuffer(), fbExtent.swizzle(0, 1),
2286                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1u,
2287                       VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
2288                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
2289 
2290     endCommandBuffer(ctx.vkd, cmdBuffer);
2291     submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
2292 
2293     // Verify color buffer has the right mip level color.
2294     const auto &colorBufferAlloc = colorBuffer.getBufferAllocation();
2295     invalidateAlloc(ctx.vkd, ctx.device, colorBufferAlloc);
2296 
2297     const tcu::ConstPixelBufferAccess resultAccess(tcuFormat, fbExtent, colorBufferAlloc.getHostPtr());
2298     const auto channelThreshold = 0.005f; // 1/255 < 0.005 < 2/255
2299     const tcu::Vec4 threshold(channelThreshold, channelThreshold, channelThreshold, 0.0f);
2300 
2301     if (!tcu::floatThresholdCompare(log, "Result", "", levelColors.at(static_cast<size_t>(accessedLevel)), resultAccess,
2302                                     threshold, tcu::COMPARE_LOG_EVERYTHING))
2303         return tcu::TestStatus::fail("Unexpected color found in color buffer -- check log for details");
2304 
2305     return tcu::TestStatus::pass("Pass");
2306 }
2307 
2308 } // namespace
2309 
createAllFormatsSamplerTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,bool separateStencilUsage=false)2310 tcu::TestCaseGroup *createAllFormatsSamplerTests(tcu::TestContext &testCtx,
2311                                                  PipelineConstructionType pipelineConstructionType,
2312                                                  bool separateStencilUsage = false)
2313 {
2314     const struct
2315     {
2316         SamplerViewType type;
2317         const char *name;
2318     } imageViewTypes[] = {{VK_IMAGE_VIEW_TYPE_1D, "1d"},
2319                           {{VK_IMAGE_VIEW_TYPE_1D, false}, "1d_unnormalized"},
2320                           {VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array"},
2321                           {VK_IMAGE_VIEW_TYPE_2D, "2d"},
2322                           {{VK_IMAGE_VIEW_TYPE_2D, false}, "2d_unnormalized"},
2323                           {VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array"},
2324                           {VK_IMAGE_VIEW_TYPE_3D, "3d"},
2325                           {VK_IMAGE_VIEW_TYPE_CUBE, "cube"},
2326                           {VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array"}};
2327 
2328     const VkFormat formats[] = {
2329         // Packed formats
2330         VK_FORMAT_R4G4_UNORM_PACK8,
2331         VK_FORMAT_R4G4B4A4_UNORM_PACK16,
2332         VK_FORMAT_R5G6B5_UNORM_PACK16,
2333         VK_FORMAT_R5G5B5A1_UNORM_PACK16,
2334         VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2335         VK_FORMAT_A2R10G10B10_UINT_PACK32,
2336         VK_FORMAT_B10G11R11_UFLOAT_PACK32,
2337         VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
2338         VK_FORMAT_B4G4R4A4_UNORM_PACK16,
2339         VK_FORMAT_B5G5R5A1_UNORM_PACK16,
2340         VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,
2341         VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,
2342 #ifndef CTS_USES_VULKANSC
2343         VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR,
2344 #endif // CTS_USES_VULKANSC
2345 
2346         // Pairwise combinations of 8-bit channel formats, UNORM/SNORM/SINT/UINT/SRGB type x 1-to-4 channels x RGBA/BGRA order
2347         VK_FORMAT_R8_SRGB,
2348         VK_FORMAT_R8G8B8_UINT,
2349         VK_FORMAT_B8G8R8A8_SINT,
2350         VK_FORMAT_R8G8_UNORM,
2351         VK_FORMAT_B8G8R8_SNORM,
2352         VK_FORMAT_R8G8B8A8_SNORM,
2353         VK_FORMAT_R8G8_UINT,
2354         VK_FORMAT_R8_SINT,
2355         VK_FORMAT_R8G8B8A8_SRGB,
2356         VK_FORMAT_R8G8B8A8_UNORM,
2357         VK_FORMAT_B8G8R8A8_UNORM,
2358         VK_FORMAT_B8G8R8_SRGB,
2359         VK_FORMAT_R8G8_SRGB,
2360         VK_FORMAT_R8_UINT,
2361         VK_FORMAT_R8G8B8A8_UINT,
2362         VK_FORMAT_R8G8_SINT,
2363         VK_FORMAT_R8_SNORM,
2364         VK_FORMAT_B8G8R8_SINT,
2365         VK_FORMAT_R8G8_SNORM,
2366         VK_FORMAT_B8G8R8_UNORM,
2367         VK_FORMAT_R8_UNORM,
2368 #ifndef CTS_USES_VULKANSC
2369         VK_FORMAT_A8_UNORM_KHR,
2370 #endif // CTS_USES_VULKANSC
2371 
2372         // Pairwise combinations of 16/32-bit channel formats x SINT/UINT/SFLOAT type x 1-to-4 channels
2373         VK_FORMAT_R32G32_SFLOAT,
2374         VK_FORMAT_R32G32B32_UINT,
2375         VK_FORMAT_R16G16B16A16_SFLOAT,
2376         VK_FORMAT_R16G16_UINT,
2377         VK_FORMAT_R32G32B32A32_SINT,
2378         VK_FORMAT_R16G16B16_SINT,
2379         VK_FORMAT_R16_SFLOAT,
2380         VK_FORMAT_R32_SINT,
2381         VK_FORMAT_R32_UINT,
2382         VK_FORMAT_R16G16B16_SFLOAT,
2383         VK_FORMAT_R16G16_SINT,
2384 
2385         // More 16/32-bit formats required for testing VK_EXT_sampler_filter_minmax
2386         VK_FORMAT_R16_SNORM,
2387         VK_FORMAT_R32_SFLOAT,
2388 
2389         // Scaled formats
2390         VK_FORMAT_R8G8B8A8_SSCALED,
2391         VK_FORMAT_A2R10G10B10_USCALED_PACK32,
2392 
2393         // Compressed formats
2394         VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
2395         VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
2396         VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
2397         VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
2398         VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
2399         VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
2400         VK_FORMAT_EAC_R11_UNORM_BLOCK,
2401         VK_FORMAT_EAC_R11_SNORM_BLOCK,
2402         VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
2403         VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
2404         VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
2405         VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
2406         VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
2407         VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
2408         VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
2409         VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
2410         VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
2411         VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
2412         VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
2413         VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
2414 
2415         // Depth formats required for testing VK_EXT_sampler_filter_minmax
2416         VK_FORMAT_D16_UNORM,
2417         VK_FORMAT_X8_D24_UNORM_PACK32,
2418         VK_FORMAT_D32_SFLOAT,
2419         VK_FORMAT_D16_UNORM_S8_UINT,
2420         VK_FORMAT_D24_UNORM_S8_UINT,
2421         VK_FORMAT_D32_SFLOAT_S8_UINT,
2422     };
2423 
2424     de::MovePtr<tcu::TestCaseGroup> viewTypeTests(new tcu::TestCaseGroup(testCtx, "view_type"));
2425 
2426     for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
2427     {
2428         const SamplerViewType viewType = imageViewTypes[viewTypeNdx].type;
2429         de::MovePtr<tcu::TestCaseGroup> viewTypeGroup(
2430             new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name));
2431         de::MovePtr<tcu::TestCaseGroup> formatTests(new tcu::TestCaseGroup(testCtx, "format"));
2432 
2433         for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
2434         {
2435             const VkFormat format     = formats[formatNdx];
2436             const bool isCompressed   = isCompressedFormat(format);
2437             const bool isDepthStencil = !isCompressed && tcu::hasDepthComponent(mapVkFormat(format).order) &&
2438                                         tcu::hasStencilComponent(mapVkFormat(format).order);
2439             if (isCompressed)
2440             {
2441                 // Do not use compressed formats with 1D and 1D array textures.
2442                 if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
2443                     break;
2444             }
2445 
2446             if (separateStencilUsage && !isDepthStencil)
2447                 continue;
2448 
2449             de::MovePtr<tcu::TestCaseGroup> formatGroup(
2450                 new tcu::TestCaseGroup(testCtx, getFormatCaseName(format).c_str()));
2451 
2452             if (!isCompressed && viewType.isNormalized())
2453             {
2454                 // Do not include minFilter tests with compressed formats.
2455                 // Randomly generated compressed textures are too noisy and will derive in false positives.
2456                 de::MovePtr<tcu::TestCaseGroup> minFilterTests = createSamplerMinFilterTests(
2457                     testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2458                 de::MovePtr<tcu::TestCaseGroup> minReduceFilterTests = createSamplerMinReduceFilterTests(
2459                     testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2460                 formatGroup->addChild(minFilterTests.release());
2461                 formatGroup->addChild(minReduceFilterTests.release());
2462             }
2463 
2464             de::MovePtr<tcu::TestCaseGroup> magFilterTests =
2465                 createSamplerMagFilterTests(testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2466             formatGroup->addChild(magFilterTests.release());
2467 
2468             if (viewType.isNormalized())
2469             {
2470                 de::MovePtr<tcu::TestCaseGroup> magReduceFilterTests = createSamplerMagReduceFilterTests(
2471                     testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2472                 de::MovePtr<tcu::TestCaseGroup> mipmapTests =
2473                     createSamplerMipmapTests(testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2474 
2475                 formatGroup->addChild(magReduceFilterTests.release());
2476                 formatGroup->addChild(mipmapTests.release());
2477             }
2478 
2479             if (viewType != VK_IMAGE_VIEW_TYPE_CUBE && viewType != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
2480             {
2481                 de::MovePtr<tcu::TestCaseGroup> addressModesTests = createSamplerAddressModesTests(
2482                     testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2483                 formatGroup->addChild(addressModesTests.release());
2484             }
2485 
2486             formatTests->addChild(formatGroup.release());
2487         }
2488 
2489         viewTypeGroup->addChild(formatTests.release());
2490         viewTypeTests->addChild(viewTypeGroup.release());
2491     }
2492 
2493     return viewTypeTests.release();
2494 }
2495 
createExactSamplingTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)2496 tcu::TestCaseGroup *createExactSamplingTests(tcu::TestContext &testCtx,
2497                                              PipelineConstructionType pipelineConstructionType)
2498 {
2499     de::MovePtr<tcu::TestCaseGroup> exactSamplingTests(new tcu::TestCaseGroup(testCtx, "exact_sampling"));
2500 
2501     static const std::vector<vk::VkFormat> formats = {
2502         vk::VK_FORMAT_R8_SRGB,          vk::VK_FORMAT_R8G8B8_UINT,       vk::VK_FORMAT_B8G8R8A8_SINT,
2503         vk::VK_FORMAT_R8G8_UNORM,       vk::VK_FORMAT_B8G8R8_SNORM,      vk::VK_FORMAT_R8G8B8A8_SNORM,
2504         vk::VK_FORMAT_R8G8_UINT,        vk::VK_FORMAT_R8_SINT,           vk::VK_FORMAT_R8G8B8A8_SRGB,
2505         vk::VK_FORMAT_R8G8B8A8_UNORM,   vk::VK_FORMAT_B8G8R8A8_UNORM,    vk::VK_FORMAT_B8G8R8_SRGB,
2506         vk::VK_FORMAT_R8G8_SRGB,        vk::VK_FORMAT_R8_UINT,           vk::VK_FORMAT_R8G8B8A8_UINT,
2507         vk::VK_FORMAT_R8G8_SINT,        vk::VK_FORMAT_R8_SNORM,          vk::VK_FORMAT_B8G8R8_SINT,
2508         vk::VK_FORMAT_R8G8_SNORM,       vk::VK_FORMAT_B8G8R8_UNORM,      vk::VK_FORMAT_R8_UNORM,
2509 #ifndef CTS_USES_VULKANSC
2510         vk::VK_FORMAT_A8_UNORM_KHR,
2511 #endif // CTS_USES_VULKANSC
2512 
2513         vk::VK_FORMAT_R32G32_SFLOAT,    vk::VK_FORMAT_R32G32B32_UINT,    vk::VK_FORMAT_R16G16B16A16_SFLOAT,
2514         vk::VK_FORMAT_R16G16_UINT,      vk::VK_FORMAT_R32G32B32A32_SINT, vk::VK_FORMAT_R16G16B16_SINT,
2515         vk::VK_FORMAT_R16_SFLOAT,       vk::VK_FORMAT_R32_SINT,          vk::VK_FORMAT_R32_UINT,
2516         vk::VK_FORMAT_R16G16B16_SFLOAT, vk::VK_FORMAT_R16G16_SINT,
2517 
2518         vk::VK_FORMAT_R16_SNORM,        vk::VK_FORMAT_R32_SFLOAT,
2519     };
2520 
2521     static const struct
2522     {
2523         const bool unnormalized;
2524         const std::string name;
2525     } unnormalizedCoordinates[] = {
2526         // Normalized coordinates
2527         {false, "normalized_coords"},
2528         // Unnormalized coordinates
2529         {true, "unnormalized_coords"},
2530     };
2531 
2532     static const struct
2533     {
2534         const tcu::Maybe<float> offset;
2535         const std::string name;
2536     } testEdges[] = {
2537         // Sampling points centered in texel
2538         {tcu::Nothing, "centered"},
2539         // Sampling points near left edge
2540         {tcu::just<float>(-1.0f), "edge_left"},
2541         // Sampling points near right edge
2542         {tcu::just<float>(+1.0f), "edge_right"},
2543     };
2544 
2545     static const std::vector<std::pair<bool, std::string>> solidColor = {
2546         {false, "gradient"},
2547         {true, "solid_color"},
2548     };
2549 
2550     for (const auto format : formats)
2551     {
2552         const std::string formatName = getFormatCaseName(format);
2553 
2554         de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str()));
2555 
2556         for (const auto &solid : solidColor)
2557         {
2558             de::MovePtr<tcu::TestCaseGroup> solidColorGroup(new tcu::TestCaseGroup(testCtx, solid.second.c_str()));
2559 
2560             for (int unIdx = 0; unIdx < DE_LENGTH_OF_ARRAY(unnormalizedCoordinates); ++unIdx)
2561             {
2562                 const auto &unnorm = unnormalizedCoordinates[unIdx];
2563                 de::MovePtr<tcu::TestCaseGroup> coordGroup(new tcu::TestCaseGroup(testCtx, unnorm.name.c_str()));
2564 
2565                 for (int edgeIdx = 0; edgeIdx < DE_LENGTH_OF_ARRAY(testEdges); ++edgeIdx)
2566                 {
2567                     const auto &edges                      = testEdges[edgeIdx];
2568                     const ExactSamplingCase::Params params = {pipelineConstructionType, format, unnorm.unnormalized,
2569                                                               solid.first, edges.offset};
2570                     coordGroup->addChild(new ExactSamplingCase{testCtx, edges.name, params});
2571                 }
2572 
2573                 solidColorGroup->addChild(coordGroup.release());
2574             }
2575 
2576             formatGroup->addChild(solidColorGroup.release());
2577         }
2578 
2579         exactSamplingTests->addChild(formatGroup.release());
2580     }
2581 
2582     return exactSamplingTests.release();
2583 }
2584 
createMaxSamplerLodBiasTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)2585 tcu::TestCaseGroup *createMaxSamplerLodBiasTests(tcu::TestContext &testCtx,
2586                                                  PipelineConstructionType pipelineConstructionType)
2587 {
2588     de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "max_sampler_lod_bias"));
2589 
2590     for (int caseIdx = 0; caseIdx < static_cast<int>(LodBiasCase::CASE_COUNT); ++caseIdx)
2591     {
2592         const auto caseValue = static_cast<LodBiasCase>(caseIdx);
2593         const auto testName  = getLodBiasCaseName(caseValue);
2594         const MaxSamplerLodBiasParams params{pipelineConstructionType, caseValue};
2595 
2596 #ifdef CTS_USES_VULKANSC
2597         if (caseValue == LodBiasCase::VIEW_MINLOD)
2598             continue;
2599 #endif // CTS_USES_VULKANSC
2600 
2601         testGroup->addChild(new MaxSamplerLodBiasCase(testCtx, testName, params));
2602     }
2603 
2604     return testGroup.release();
2605 }
2606 
createSamplerTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)2607 tcu::TestCaseGroup *createSamplerTests(tcu::TestContext &testCtx, PipelineConstructionType pipelineConstructionType)
2608 {
2609     const auto genAllTests = (pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC ||
2610                               pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_SPIRV);
2611 
2612     de::MovePtr<tcu::TestCaseGroup> samplerTests(new tcu::TestCaseGroup(testCtx, "sampler"));
2613     {
2614         if (genAllTests)
2615             samplerTests->addChild(createAllFormatsSamplerTests(testCtx, pipelineConstructionType));
2616         samplerTests->addChild(createExactSamplingTests(testCtx, pipelineConstructionType));
2617     }
2618 
2619     // tests for VK_EXT_separate_stencil_usage
2620     de::MovePtr<tcu::TestCaseGroup> separateStencilUsageSamplerTests(
2621         new tcu::TestCaseGroup(testCtx, "separate_stencil_usage"));
2622     {
2623         separateStencilUsageSamplerTests->addChild(
2624             createAllFormatsSamplerTests(testCtx, pipelineConstructionType, true));
2625         samplerTests->addChild(separateStencilUsageSamplerTests.release());
2626     }
2627 
2628 #ifndef CTS_USES_VULKANSC
2629     // Border color swizzle tests.
2630     if (genAllTests)
2631         samplerTests->addChild(createSamplerBorderSwizzleTests(testCtx, pipelineConstructionType));
2632 #endif // CTS_USES_VULKANSC
2633 
2634     samplerTests->addChild(createMaxSamplerLodBiasTests(testCtx, pipelineConstructionType));
2635 
2636     return samplerTests.release();
2637 }
2638 
2639 } // namespace pipeline
2640 } // namespace vkt
2641