• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     if (m_params.offsetSign)
1608     {
1609         const float sign = m_params.offsetSign.get();
1610         DE_ASSERT(sign == 1.0f || sign == -1.0f);
1611         const float offsetWidth  = 0.499f / static_cast<float>(texExtent.width);
1612         const float offsetHeight = 0.499f / static_cast<float>(texExtent.height);
1613 
1614         minU += sign * offsetWidth;
1615         maxU += sign * offsetWidth;
1616         minV += sign * offsetHeight;
1617         maxV += sign * offsetHeight;
1618     }
1619 
1620     const std::vector<ExactSamplingCase::VertexData> fullScreenQuad = {
1621         {
1622             {1.f, -1.f},
1623             {maxU, minV},
1624         },
1625         {
1626             {-1.f, -1.f},
1627             {minU, minV},
1628         },
1629         {
1630             {-1.f, 1.f},
1631             {minU, maxV},
1632         },
1633         {
1634             {-1.f, 1.f},
1635             {minU, maxV},
1636         },
1637         {
1638             {1.f, -1.f},
1639             {maxU, minV},
1640         },
1641         {
1642             {1.f, 1.f},
1643             {maxU, maxV},
1644         },
1645     };
1646 
1647     // Vertex buffer.
1648     const vk::VkDeviceSize vertexBufferSize =
1649         static_cast<vk::VkDeviceSize>(fullScreenQuad.size() * sizeof(decltype(fullScreenQuad)::value_type));
1650     const auto vertexBufferInfo = vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1651     const vk::BufferWithMemory vertexBuffer{vkd, device, allocator, vertexBufferInfo,
1652                                             vk::MemoryRequirement::HostVisible};
1653 
1654     // Copy data to vertex buffer.
1655     const auto &vertexAlloc  = vertexBuffer.getAllocation();
1656     const auto vertexDataPtr = reinterpret_cast<char *>(vertexAlloc.getHostPtr()) + vertexAlloc.getOffset();
1657     deMemcpy(vertexDataPtr, fullScreenQuad.data(), static_cast<size_t>(vertexBufferSize));
1658     vk::flushAlloc(vkd, device, vertexAlloc);
1659 
1660     // Descriptor set layout.
1661     vk::DescriptorSetLayoutBuilder layoutBuilder;
1662     layoutBuilder.addSingleBinding(descType, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
1663     const auto descriptorSetLayout = layoutBuilder.build(vkd, device);
1664 
1665     // Descriptor pool.
1666     vk::DescriptorPoolBuilder poolBuilder;
1667     poolBuilder.addType(descType);
1668     const auto descriptorPool =
1669         poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1670 
1671     // Descriptor set.
1672     const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.get());
1673 
1674     // Texture sampler. When using a solid color, test linear filtering. Linear filtering may incur in a small precission loss, but
1675     // it should be minimal and we should get the same color when converting back to the original format.
1676     const auto minMagFilter = (m_params.solidColor ? vk::VK_FILTER_LINEAR : vk::VK_FILTER_NEAREST);
1677     const auto addressMode  = (unnorm ? vk::VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE : vk::VK_SAMPLER_ADDRESS_MODE_REPEAT);
1678     const auto unnormalizedCoordinates = (unnorm ? VK_TRUE : VK_FALSE);
1679 
1680     const vk::VkSamplerCreateInfo samplerCreateInfo = {
1681         vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,   // VkStructureType sType;
1682         nullptr,                                     // const void* pNext;
1683         0u,                                          // VkSamplerCreateFlags flags;
1684         minMagFilter,                                // VkFilter magFilter;
1685         minMagFilter,                                // VkFilter minFilter;
1686         vk::VK_SAMPLER_MIPMAP_MODE_NEAREST,          // VkSamplerMipmapMode mipmapMode;
1687         addressMode,                                 // VkSamplerAddressMode addressModeU;
1688         addressMode,                                 // VkSamplerAddressMode addressModeV;
1689         addressMode,                                 // VkSamplerAddressMode addressModeW;
1690         0.0f,                                        // float mipLodBias;
1691         VK_FALSE,                                    // VkBool32 anisotropyEnable;
1692         1.0f,                                        // float maxAnisotropy;
1693         VK_FALSE,                                    // VkBool32 compareEnable;
1694         vk::VK_COMPARE_OP_NEVER,                     // VkCompareOp compareOp;
1695         0.0f,                                        // float minLod;
1696         0.0f,                                        // float maxLod;
1697         vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
1698         unnormalizedCoordinates,                     // VkBool32 unnormalizedCoordinates;
1699     };
1700     const auto texSampler = vk::createSampler(vkd, device, &samplerCreateInfo);
1701 
1702     // Update descriptor set with the descriptor.
1703     vk::DescriptorSetUpdateBuilder updateBuilder;
1704     const auto descriptorImageInfo = vk::makeDescriptorImageInfo(texSampler.get(), texView.get(), texLayout);
1705     updateBuilder.writeSingle(descriptorSet.get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), descType,
1706                               &descriptorImageInfo);
1707     updateBuilder.update(vkd, device);
1708 
1709     // Shader modules.
1710     const auto vertexModule = vk::ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
1711     const auto fragModule   = vk::ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);
1712 
1713     // Render pass.
1714     const vk::VkAttachmentDescription fbAttachment = {
1715         0u,                                           // VkAttachmentDescriptionFlags flags;
1716         m_params.format,                              // VkFormat format;
1717         vk::VK_SAMPLE_COUNT_1_BIT,                    // VkSampleCountFlagBits samples;
1718         vk::VK_ATTACHMENT_LOAD_OP_CLEAR,              // VkAttachmentLoadOp loadOp;
1719         vk::VK_ATTACHMENT_STORE_OP_STORE,             // VkAttachmentStoreOp storeOp;
1720         vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,          // VkAttachmentLoadOp stencilLoadOp;
1721         vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,         // VkAttachmentStoreOp stencilStoreOp;
1722         vk::VK_IMAGE_LAYOUT_UNDEFINED,                // VkImageLayout initialLayout;
1723         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout;
1724     };
1725 
1726     const vk::VkAttachmentReference colorRef = {
1727         0u,                                           // uint32_t attachment;
1728         vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout;
1729     };
1730 
1731     const vk::VkSubpassDescription subpass = {
1732         0u,                                  // VkSubpassDescriptionFlags flags;
1733         vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
1734         0u,                                  // uint32_t inputAttachmentCount;
1735         nullptr,                             // const VkAttachmentReference* pInputAttachments;
1736         1u,                                  // uint32_t colorAttachmentCount;
1737         &colorRef,                           // const VkAttachmentReference* pColorAttachments;
1738         0u,                                  // const VkAttachmentReference* pResolveAttachments;
1739         nullptr,                             // const VkAttachmentReference* pDepthStencilAttachment;
1740         0u,                                  // uint32_t preserveAttachmentCount;
1741         nullptr,                             // const uint32_t* pPreserveAttachments;
1742     };
1743 
1744     const vk::VkRenderPassCreateInfo renderPassInfo = {
1745         vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
1746         nullptr,                                       // const void* pNext;
1747         0u,                                            // VkRenderPassCreateFlags flags;
1748         1u,                                            // uint32_t attachmentCount;
1749         &fbAttachment,                                 // const VkAttachmentDescription* pAttachments;
1750         1u,                                            // uint32_t subpassCount;
1751         &subpass,                                      // const VkSubpassDescription* pSubpasses;
1752         0u,                                            // uint32_t dependencyCount;
1753         nullptr,                                       // const VkSubpassDependency* pDependencies;
1754     };
1755     RenderPassWrapper renderPass(m_params.pipelineConstructionType, vkd, device, &renderPassInfo);
1756 
1757     // Framebuffer.
1758     std::vector<vk::VkImageView> attachments;
1759     attachments.push_back(fbView.get());
1760     renderPass.createFramebuffer(vkd, device, 1u, &fbImage.get(), &fbView.get(), texExtent.width, texExtent.height,
1761                                  texExtent.depth);
1762 
1763     // Push constant range.
1764     const vk::VkPushConstantRange pcRange = {
1765         vk::VK_SHADER_STAGE_VERTEX_BIT,                                  // VkShaderStageFlags stageFlags;
1766         0u,                                                              // uint32_t offset;
1767         static_cast<uint32_t>(sizeof(ExactSamplingCase::PushConstants)), // uint32_t size;
1768     };
1769 
1770     // Pipeline layout.
1771     const vk::VkPipelineLayoutCreateInfo pipelineLayoutInfo = {
1772         vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
1773         nullptr,                                           // const void* pNext;
1774         0u,                                                // VkPipelineLayoutCreateFlags flags;
1775         1u,                                                // uint32_t setLayoutCount;
1776         &descriptorSetLayout.get(),                        // const VkDescriptorSetLayout* pSetLayouts;
1777         1u,                                                // uint32_t pushConstantRangeCount;
1778         &pcRange,                                          // const VkPushConstantRange* pPushConstantRanges;
1779     };
1780     const vk::PipelineLayoutWrapper pipelineLayout(m_params.pipelineConstructionType, vkd, device, &pipelineLayoutInfo);
1781 
1782     // Graphics pipeline.
1783     const std::vector<vk::VkViewport> viewports{vk::makeViewport(texExtent)};
1784     const vk::VkRect2D renderArea = vk::makeRect2D(texExtent);
1785     const std::vector<vk::VkRect2D> scissors{renderArea};
1786 
1787     const auto vtxBindingDescription    = ExactSamplingCase::VertexData::getBindingDescription();
1788     const auto vtxAttributeDescriptions = ExactSamplingCase::VertexData::getAttributeDescriptions();
1789 
1790     const vk::VkPipelineVertexInputStateCreateInfo vertexInputInfo = {
1791         vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType                             sType
1792         nullptr,                // const void*                                 pNext
1793         0u,                     // VkPipelineVertexInputStateCreateFlags       flags
1794         1u,                     // uint32_t                                    vertexBindingDescriptionCount
1795         &vtxBindingDescription, // const VkVertexInputBindingDescription*      pVertexBindingDescriptions
1796         static_cast<uint32_t>(
1797             vtxAttributeDescriptions
1798                 .size()),                // uint32_t                                    vertexAttributeDescriptionCount
1799         vtxAttributeDescriptions.data(), // const VkVertexInputAttributeDescription*    pVertexAttributeDescriptions
1800     };
1801 
1802     GraphicsPipelineWrapper pipeline(vki, vkd, physDevice, device, m_context.getDeviceExtensions(),
1803                                      m_params.pipelineConstructionType);
1804     pipeline.setDefaultDepthStencilState()
1805         .setDefaultRasterizationState()
1806         .setDefaultMultisampleState()
1807         .setDefaultColorBlendState()
1808         .setupVertexInputState(&vertexInputInfo)
1809         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertexModule)
1810         .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragModule)
1811         .setupFragmentOutputState(*renderPass)
1812         .setMonolithicPipelineLayout(pipelineLayout)
1813         .buildPipeline();
1814 
1815     // Command pool and command buffer.
1816     const auto cmdPool =
1817         vk::createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueIndex);
1818     const auto cmdBufferPtr =
1819         vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1820     const auto cmdBuffer = cmdBufferPtr.get();
1821 
1822     // Draw quad.
1823     const ExactSamplingCase::PushConstants pushConstants = {
1824         static_cast<float>(texExtent.width),
1825         static_cast<float>(texExtent.height),
1826     };
1827 
1828     const tcu::Vec4 clearFbColor(0.0f, 0.0f, 0.0f, 1.0f);
1829     const vk::VkDeviceSize vertexBufferOffset = 0ull;
1830 
1831     const auto vertexBufferBarrier =
1832         vk::makeBufferMemoryBarrier(vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT,
1833                                     vertexBuffer.get(), 0ull, vertexBufferSize);
1834     const auto preBufferCopyBarrier = vk::makeBufferMemoryBarrier(
1835         vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, texBuffer.get(), 0ull, texBufferSize);
1836     const auto preTexCopyBarrier =
1837         vk::makeImageMemoryBarrier(0u, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED,
1838                                    vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texImage.get(), colorSubresourceRange);
1839     const auto postTexCopyBarrier = vk::makeImageMemoryBarrier(
1840         vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_SHADER_READ_BIT, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1841         texLayout, texImage.get(), colorSubresourceRange);
1842     const auto texCopyRange = vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
1843     const auto texImageCopy = vk::makeBufferImageCopy(texExtent, texCopyRange);
1844 
1845     vk::beginCommandBuffer(vkd, cmdBuffer);
1846 
1847     vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u, 0u,
1848                            nullptr, 1u, &vertexBufferBarrier, 0u, nullptr);
1849     vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
1850                            nullptr, 1u, &preBufferCopyBarrier, 0u, nullptr);
1851     vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u,
1852                            nullptr, 0u, nullptr, 1u, &preTexCopyBarrier);
1853     vkd.cmdCopyBufferToImage(cmdBuffer, texBuffer.get(), texImage.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u,
1854                              &texImageCopy);
1855     vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u,
1856                            0u, nullptr, 0u, nullptr, 1u, &postTexCopyBarrier);
1857 
1858     renderPass.begin(vkd, cmdBuffer, renderArea, clearFbColor);
1859     pipeline.bind(cmdBuffer);
1860     vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u,
1861                               &descriptorSet.get(), 0u, nullptr);
1862     vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1863     vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), vk::VK_SHADER_STAGE_VERTEX_BIT, 0u,
1864                          static_cast<uint32_t>(sizeof(pushConstants)), &pushConstants);
1865     vkd.cmdDraw(cmdBuffer, static_cast<uint32_t>(fullScreenQuad.size()), 1u, 0u, 0u);
1866     renderPass.end(vkd, cmdBuffer);
1867 
1868     vk::copyImageToBuffer(vkd, cmdBuffer, fbImage.get(), resultsBuffer.get(), iImgSize);
1869 
1870     vk::endCommandBuffer(vkd, cmdBuffer);
1871     vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
1872 
1873     // Check results.
1874     const auto &resultsBufferAlloc = resultsBuffer.getAllocation();
1875     vk::invalidateAlloc(vkd, device, resultsBufferAlloc);
1876 
1877     const auto resultsBufferPtr =
1878         reinterpret_cast<const char *>(resultsBufferAlloc.getHostPtr()) + resultsBufferAlloc.getOffset();
1879     const tcu::ConstPixelBufferAccess resultPixels{tcuFormat, iImgSize[0], iImgSize[1], 1, resultsBufferPtr};
1880 
1881     const tcu::TextureFormat diffFormat{tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8};
1882     const auto diffBytes = tcu::getPixelSize(diffFormat) * iImgSize[0] * iImgSize[1];
1883     std::unique_ptr<uint8_t[]> diffData{new uint8_t[diffBytes]};
1884     const tcu::PixelBufferAccess diffImg{diffFormat, iImgSize[0], iImgSize[1], 1, diffData.get()};
1885 
1886     const tcu::Vec4 colorRed{1.0f, 0.0f, 0.0f, 1.0f};
1887     const tcu::Vec4 colorGreen{0.0f, 1.0f, 0.0f, 1.0f};
1888 
1889     // Clear diff image.
1890     deMemset(diffData.get(), 0, static_cast<size_t>(diffBytes));
1891 
1892     bool pass = true;
1893     for (int x = 0; x < W; ++x)
1894         for (int y = 0; y < H; ++y)
1895             for (int z = 0; z < D; ++z)
1896             {
1897                 const auto inPix  = texPixels.getPixel(x, y, z);
1898                 const auto outPix = resultPixels.getPixel(x, y, z);
1899                 if (inPix == outPix)
1900                 {
1901                     diffImg.setPixel(colorGreen, x, y, z);
1902                 }
1903                 else
1904                 {
1905                     pass = false;
1906                     diffImg.setPixel(colorRed, x, y, z);
1907                 }
1908             }
1909 
1910     tcu::TestStatus status = tcu::TestStatus::pass("Pass");
1911     if (!pass)
1912     {
1913         auto &log = m_context.getTestContext().getLog();
1914         log << tcu::TestLog::Image("input", "Input texture", texPixels);
1915         log << tcu::TestLog::Image("output", "Rendered image", resultPixels);
1916         log << tcu::TestLog::Image("diff", "Mismatched pixels in red", diffImg);
1917         status = tcu::TestStatus::fail("Pixel mismatch; please check the rendered image");
1918     }
1919 
1920     return status;
1921 }
1922 
1923 enum class LodBiasCase
1924 {
1925     SAMPLER_BIAS   = 0,
1926     SAMPLER_MINLOD = 1,
1927     SHADER_LOD     = 2,
1928     SHADER_BIAS    = 3,
1929     VIEW_MINLOD    = 4,
1930     CASE_COUNT     = 5,
1931 };
1932 
getLodBiasCaseName(LodBiasCase lodBiasCase)1933 std::string getLodBiasCaseName(LodBiasCase lodBiasCase)
1934 {
1935     std::string name;
1936 
1937     switch (lodBiasCase)
1938     {
1939     case LodBiasCase::SAMPLER_BIAS:
1940         name = "sampler_bias";
1941         break;
1942     case LodBiasCase::SAMPLER_MINLOD:
1943         name = "sampler_minlod";
1944         break;
1945     case LodBiasCase::SHADER_LOD:
1946         name = "shader_lod";
1947         break;
1948     case LodBiasCase::SHADER_BIAS:
1949         name = "shader_bias";
1950         break;
1951     case LodBiasCase::VIEW_MINLOD:
1952         name = "view_minlod";
1953         break;
1954     case LodBiasCase::CASE_COUNT: // fallthrough
1955     default:
1956         DE_ASSERT(false);
1957         break;
1958     }
1959 
1960     return name;
1961 }
1962 
1963 struct MaxSamplerLodBiasParams
1964 {
1965     const PipelineConstructionType pipelineConstructionType;
1966     const LodBiasCase lodBiasCase;
1967 };
1968 
1969 class MaxSamplerLodBiasCase : public vkt::TestCase
1970 {
1971 public:
MaxSamplerLodBiasCase(tcu::TestContext & testCtx,const std::string & name,const MaxSamplerLodBiasParams & params)1972     MaxSamplerLodBiasCase(tcu::TestContext &testCtx, const std::string &name, const MaxSamplerLodBiasParams &params)
1973         : vkt::TestCase(testCtx, name)
1974         , m_params(params)
1975     {
1976     }
~MaxSamplerLodBiasCase(void)1977     virtual ~MaxSamplerLodBiasCase(void)
1978     {
1979     }
1980 
1981     void checkSupport(Context &context) const override;
1982     void initPrograms(vk::SourceCollections &programCollection) const override;
1983     TestInstance *createInstance(Context &context) const override;
1984 
1985 protected:
1986     const MaxSamplerLodBiasParams m_params;
1987 };
1988 
1989 class MaxSamplerLodBiasInstance : public vkt::TestInstance
1990 {
1991 public:
MaxSamplerLodBiasInstance(Context & context,const MaxSamplerLodBiasParams & params)1992     MaxSamplerLodBiasInstance(Context &context, const MaxSamplerLodBiasParams &params)
1993         : vkt::TestInstance(context)
1994         , m_params(params)
1995     {
1996     }
~MaxSamplerLodBiasInstance(void)1997     virtual ~MaxSamplerLodBiasInstance(void)
1998     {
1999     }
2000 
2001     tcu::TestStatus iterate(void);
2002 
2003 protected:
2004     const MaxSamplerLodBiasParams m_params;
2005 };
2006 
checkSupport(Context & context) const2007 void MaxSamplerLodBiasCase::checkSupport(Context &context) const
2008 {
2009     checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(),
2010                                           m_params.pipelineConstructionType);
2011 
2012     if (m_params.lodBiasCase == LodBiasCase::VIEW_MINLOD)
2013         context.requireDeviceFunctionality("VK_EXT_image_view_min_lod");
2014 }
2015 
initPrograms(vk::SourceCollections & programCollection) const2016 void MaxSamplerLodBiasCase::initPrograms(vk::SourceCollections &programCollection) const
2017 {
2018     std::ostringstream vert;
2019     vert << "#version 460\n"
2020          << "layout (location=0) in vec4 inPos;\n"
2021          << "void main (void) {\n"
2022          << "    gl_Position = inPos;\n"
2023          << "}\n";
2024     programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
2025 
2026     std::string sampleStatement;
2027     const std::string sampleCoords = "vec2(gl_FragCoord.x / pc.fbWidth, gl_FragCoord.y / pc.fbHeight)";
2028 
2029     if (m_params.lodBiasCase == LodBiasCase::SHADER_LOD)
2030         sampleStatement = "textureLod(texSampler, " + sampleCoords + ", pc.lodLevel)";
2031     else if (m_params.lodBiasCase == LodBiasCase::SHADER_BIAS)
2032         sampleStatement = "texture(texSampler, " + sampleCoords + ", pc.lodLevel)";
2033     else
2034         sampleStatement = "textureLod(texSampler, " + sampleCoords + ", 0.0)";
2035 
2036     DE_ASSERT(!sampleStatement.empty());
2037 
2038     std::ostringstream frag;
2039     frag << "#version 460\n"
2040          << "layout (location=0) out vec4 outColor;\n"
2041          << "layout (set=0, binding=0) uniform sampler2D texSampler;\n"
2042          << "layout (push_constant, std430) uniform PushConstantBlock {\n"
2043          << "    float lodLevel;\n"
2044          << "    float fbWidth;\n"
2045          << "    float fbHeight;\n"
2046          << "} pc;\n"
2047          << "void main (void) {\n"
2048          << "    outColor = " << sampleStatement << ";\n"
2049          << "}\n";
2050     programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
2051 }
2052 
createInstance(Context & context) const2053 TestInstance *MaxSamplerLodBiasCase::createInstance(Context &context) const
2054 {
2055     return new MaxSamplerLodBiasInstance(context, m_params);
2056 }
2057 
iterate(void)2058 tcu::TestStatus MaxSamplerLodBiasInstance::iterate(void)
2059 {
2060     const auto ctx               = m_context.getContextCommonData();
2061     const auto vkFormat          = VK_FORMAT_R8G8B8A8_UNORM;
2062     const auto tcuFormat         = mapVkFormat(vkFormat);
2063     const auto imageType         = VK_IMAGE_TYPE_2D;
2064     const auto tiling            = VK_IMAGE_TILING_OPTIMAL;
2065     const auto textureUsage      = (VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
2066     const auto fbUsage           = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
2067     const auto sampleCount       = VK_SAMPLE_COUNT_1_BIT;
2068     const auto descriptorType    = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
2069     const auto maxLodBias        = getPhysicalDeviceProperties(ctx.vki, ctx.physicalDevice).limits.maxSamplerLodBias;
2070     const auto roundedBias       = deFloatFloor(maxLodBias + 0.5f);
2071     const auto textureProperties = getPhysicalDeviceImageFormatProperties(ctx.vki, ctx.physicalDevice, vkFormat,
2072                                                                           imageType, tiling, textureUsage, 0u);
2073     const auto textureExtent     = makeExtent3D(textureProperties.maxExtent.width, 1u, 1u);
2074     const auto fbExtent          = tcu::IVec3(1, 1, 1);
2075     const auto vkExtent          = makeExtent3D(fbExtent);
2076     const auto baseSeed          = 1687852938u;
2077 
2078     const VkImageCreateInfo textureCreateInfo = {
2079         VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
2080         nullptr,                             // const void* pNext;
2081         0u,                                  // VkImageCreateFlags flags;
2082         imageType,                           // VkImageType imageType;
2083         vkFormat,                            // VkFormat format;
2084         textureExtent,                       // VkExtent3D extent;
2085         textureProperties.maxMipLevels,      // uint32_t mipLevels;
2086         1u,                                  // uint32_t arrayLayers;
2087         sampleCount,                         // VkSampleCountFlagBits samples;
2088         tiling,                              // VkImageTiling tiling;
2089         textureUsage,                        // VkImageUsageFlags usage;
2090         VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode sharingMode;
2091         0u,                                  // uint32_t queueFamilyIndexCount;
2092         nullptr,                             // const uint32_t* pQueueFamilyIndices;
2093         VK_IMAGE_LAYOUT_UNDEFINED,           // VkImageLayout initialLayout;
2094     };
2095     ImageWithMemory texture(ctx.vkd, ctx.device, ctx.allocator, textureCreateInfo, MemoryRequirement::Any);
2096     const auto textureColorSRR =
2097         makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, textureCreateInfo.mipLevels, 0u, 1u);
2098     const auto accessedLevel = std::min(roundedBias, static_cast<float>(textureCreateInfo.mipLevels - 1u));
2099 
2100 #ifndef CTS_USES_VULKANSC
2101     std::unique_ptr<VkImageViewMinLodCreateInfoEXT> viewMinLodPtr;
2102     if (m_params.lodBiasCase == LodBiasCase::VIEW_MINLOD)
2103     {
2104         viewMinLodPtr.reset(new VkImageViewMinLodCreateInfoEXT{
2105             VK_STRUCTURE_TYPE_IMAGE_VIEW_MIN_LOD_CREATE_INFO_EXT, nullptr,
2106             accessedLevel, // VUID-VkImageViewMinLodCreateInfoEXT-minLod-06456 prevents us from using maxLodBias directly.
2107         });
2108     }
2109 #endif // CTS_USES_VULKANSC
2110 
2111     const VkImageViewCreateInfo viewCreateInfo = {
2112         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
2113 #ifndef CTS_USES_VULKANSC
2114         viewMinLodPtr.get(), // const void* pNext;
2115 #else
2116         nullptr, // const void* pNext;
2117 #endif                         // CTS_USES_VULKANSC
2118         0u,                    // VkImageViewCreateFlags flags;
2119         texture.get(),         // VkImage image;
2120         VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
2121         vkFormat,              // VkFormat format;
2122         {
2123             // VkComponentMapping components;
2124             VK_COMPONENT_SWIZZLE_R,
2125             VK_COMPONENT_SWIZZLE_G,
2126             VK_COMPONENT_SWIZZLE_B,
2127             VK_COMPONENT_SWIZZLE_A,
2128         },
2129         textureColorSRR, // VkImageSubresourceRange subresourceRange;
2130     };
2131     const auto textureView = createImageView(ctx.vkd, ctx.device, &viewCreateInfo);
2132 
2133     // Output color buffer.
2134     ImageWithBuffer colorBuffer(ctx.vkd, ctx.device, ctx.allocator, vkExtent, vkFormat, fbUsage, imageType);
2135 
2136     // Texture sampler.
2137     const float samplerMipLodBias = ((m_params.lodBiasCase == LodBiasCase::SAMPLER_BIAS) ? maxLodBias : 0.0f);
2138     const float samplerMinLod     = ((m_params.lodBiasCase == LodBiasCase::SAMPLER_MINLOD) ? maxLodBias : 0.0f);
2139     const VkSamplerCreateInfo samplerCreateInfo = {
2140         VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,   // VkStructureType sType;
2141         nullptr,                                 // const void* pNext;
2142         0u,                                      // VkSamplerCreateFlags flags;
2143         VK_FILTER_NEAREST,                       // VkFilter magFilter;
2144         VK_FILTER_NEAREST,                       // VkFilter minFilter;
2145         VK_SAMPLER_MIPMAP_MODE_NEAREST,          // VkSamplerMipmapMode mipmapMode;
2146         VK_SAMPLER_ADDRESS_MODE_REPEAT,          // VkSamplerAddressMode addressModeU;
2147         VK_SAMPLER_ADDRESS_MODE_REPEAT,          // VkSamplerAddressMode addressModeV;
2148         VK_SAMPLER_ADDRESS_MODE_REPEAT,          // VkSamplerAddressMode addressModeW;
2149         samplerMipLodBias,                       // float mipLodBias;
2150         VK_FALSE,                                // VkBool32 anisotropyEnable;
2151         0.0f,                                    // float maxAnisotropy;
2152         VK_FALSE,                                // VkBool32 compareEnable;
2153         VK_COMPARE_OP_NEVER,                     // VkCompareOp compareOp;
2154         samplerMinLod,                           // float minLod;
2155         VK_LOD_CLAMP_NONE,                       // float maxLod;
2156         VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor borderColor;
2157         VK_FALSE,                                // VkBool32 unnormalizedCoordinates;
2158     };
2159     const auto sampler = createSampler(ctx.vkd, ctx.device, &samplerCreateInfo);
2160 
2161     // Vertex buffer.
2162     const std::vector<tcu::Vec4> vertices{
2163         tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
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     };
2168     const auto vertexBufferSize = static_cast<VkDeviceSize>(de::dataSize(vertices));
2169     const auto vertexBufferInfo = makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
2170     BufferWithMemory vertexBuffer(ctx.vkd, ctx.device, ctx.allocator, vertexBufferInfo, MemoryRequirement::HostVisible);
2171     auto &vertexBufferAlloc       = vertexBuffer.getAllocation();
2172     void *vertexBufferDataPtr     = vertexBufferAlloc.getHostPtr();
2173     const auto vertexBufferOffset = static_cast<VkDeviceSize>(0);
2174 
2175     deMemcpy(vertexBufferDataPtr, de::dataOrNull(vertices), de::dataSize(vertices));
2176     flushAlloc(ctx.vkd, ctx.device, vertexBufferAlloc);
2177 
2178     // Render pass and framebuffer.
2179     auto renderPass = RenderPassWrapper(m_params.pipelineConstructionType, ctx.vkd, ctx.device, vkFormat);
2180     renderPass.createFramebuffer(ctx.vkd, ctx.device, colorBuffer.getImage(), colorBuffer.getImageView(),
2181                                  vkExtent.width, vkExtent.height);
2182 
2183     // Push constants.
2184     const std::vector<float> pcValues{maxLodBias, static_cast<float>(vkExtent.width),
2185                                       static_cast<float>(vkExtent.height)};
2186     const auto pcSize   = static_cast<uint32_t>(de::dataSize(pcValues));
2187     const auto pcStages = VK_SHADER_STAGE_FRAGMENT_BIT;
2188     const auto pcRange  = makePushConstantRange(pcStages, 0u, pcSize);
2189 
2190     // Descriptor pool and set.
2191     DescriptorSetLayoutBuilder setLayoutBuilder;
2192     setLayoutBuilder.addSingleBinding(descriptorType, VK_SHADER_STAGE_FRAGMENT_BIT);
2193     const auto descriptorSetLayout = setLayoutBuilder.build(ctx.vkd, ctx.device);
2194     const PipelineLayoutWrapper pipelineLayout(m_params.pipelineConstructionType, ctx.vkd, ctx.device,
2195                                                *descriptorSetLayout, &pcRange);
2196 
2197     DescriptorPoolBuilder descriptorPoolBuilder;
2198     descriptorPoolBuilder.addType(descriptorType);
2199     const auto descriptorPool =
2200         descriptorPoolBuilder.build(ctx.vkd, ctx.device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2201     const auto descriptorSet = makeDescriptorSet(ctx.vkd, ctx.device, *descriptorPool, *descriptorSetLayout);
2202 
2203     DescriptorSetUpdateBuilder setUpdateBuilder;
2204     const auto samplerDescriptorInfo =
2205         makeDescriptorImageInfo(*sampler, *textureView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
2206     setUpdateBuilder.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), descriptorType,
2207                                  &samplerDescriptorInfo);
2208     setUpdateBuilder.update(ctx.vkd, ctx.device);
2209 
2210     // Pipeline.
2211     const auto &binaries = m_context.getBinaryCollection();
2212     const auto vertMod   = ShaderWrapper(ctx.vkd, ctx.device, binaries.get("vert"));
2213     const auto fragMod   = ShaderWrapper(ctx.vkd, ctx.device, binaries.get("frag"));
2214 
2215     const std::vector<VkViewport> viewports(1u, makeViewport(vkExtent));
2216     const std::vector<VkRect2D> scissors(1u, makeRect2D(vkExtent));
2217 
2218     GraphicsPipelineWrapper pipeline(ctx.vki, ctx.vkd, ctx.physicalDevice, ctx.device, m_context.getDeviceExtensions(),
2219                                      m_params.pipelineConstructionType);
2220     pipeline.setDefaultDepthStencilState()
2221         .setDefaultRasterizationState()
2222         .setDefaultMultisampleState()
2223         .setDefaultColorBlendState()
2224         .setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
2225         .setupVertexInputState()
2226         .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, *renderPass, 0u, vertMod)
2227         .setupFragmentShaderState(pipelineLayout, *renderPass, 0u, fragMod)
2228         .setupFragmentOutputState(*renderPass)
2229         .setMonolithicPipelineLayout(pipelineLayout)
2230         .buildPipeline();
2231 
2232     CommandPoolWithBuffer cmd(ctx.vkd, ctx.device, ctx.qfIndex);
2233     const auto cmdBuffer = *cmd.cmdBuffer;
2234 
2235     beginCommandBuffer(ctx.vkd, cmdBuffer);
2236 
2237     // Transition texture to layout suitable for filling.
2238     const auto preFillBarrier =
2239         makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
2240                                VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, texture.get(), textureColorSRR);
2241     cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
2242                                   &preFillBarrier);
2243 
2244     // Fill every level with a different random color.
2245     auto &log = m_context.getTestContext().getLog();
2246     de::Random rnd(baseSeed + static_cast<uint32_t>(m_params.lodBiasCase));
2247     std::vector<tcu::Vec4> levelColors;
2248     levelColors.reserve(textureCreateInfo.mipLevels);
2249 
2250     for (uint32_t level = 0u; level < textureCreateInfo.mipLevels; ++level)
2251     {
2252         const auto levelRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, level, 1u, 0u, 1u);
2253         // If we "embed" these expressions in the constructor below, separated by commas, the order in which colors are obtained would depend on the compiler.
2254         const auto red   = rnd.getFloat(0.0f, 1.0f);
2255         const auto green = rnd.getFloat(0.0f, 1.0f);
2256         const auto blue  = rnd.getFloat(0.0f, 1.0f);
2257         const tcu::Vec4 clearValue(red, green, blue, 1.0f);
2258         const auto clearValueColor = makeClearValueColorVec4(clearValue);
2259 
2260         levelColors.push_back(clearValue);
2261         ctx.vkd.cmdClearColorImage(cmdBuffer, texture.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2262                                    &clearValueColor.color, 1u, &levelRange);
2263         log << tcu::TestLog::Message << "Level " << level << " cleared to " << clearValue << tcu::TestLog::EndMessage;
2264     }
2265 
2266     // Transition texture to suitable layout for reading it in the shader.
2267     const auto preReadBarrier = makeImageMemoryBarrier(
2268         VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
2269         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, texture.get(), textureColorSRR);
2270     cmdPipelineImageMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
2271                                   VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, &preReadBarrier);
2272 
2273     const tcu::Vec4 fbClearColor(0.0f, 0.0f, 0.0f, 0.0f);
2274     renderPass.begin(ctx.vkd, cmdBuffer, scissors.at(0u), fbClearColor);
2275     ctx.vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
2276     pipeline.bind(cmdBuffer);
2277     ctx.vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u,
2278                                   &descriptorSet.get(), 0u, nullptr);
2279     ctx.vkd.cmdPushConstants(cmdBuffer, *pipelineLayout, pcStages, 0u, pcSize, de::dataOrNull(pcValues));
2280     ctx.vkd.cmdDraw(cmdBuffer, de::sizeU32(vertices), 1u, 0u, 0u);
2281     renderPass.end(ctx.vkd, cmdBuffer);
2282 
2283     // Copy color buffer to verification buffer.
2284     copyImageToBuffer(ctx.vkd, cmdBuffer, colorBuffer.getImage(), colorBuffer.getBuffer(), fbExtent.swizzle(0, 1),
2285                       VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1u,
2286                       VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT,
2287                       VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
2288 
2289     endCommandBuffer(ctx.vkd, cmdBuffer);
2290     submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
2291 
2292     // Verify color buffer has the right mip level color.
2293     const auto &colorBufferAlloc = colorBuffer.getBufferAllocation();
2294     invalidateAlloc(ctx.vkd, ctx.device, colorBufferAlloc);
2295 
2296     const tcu::ConstPixelBufferAccess resultAccess(tcuFormat, fbExtent, colorBufferAlloc.getHostPtr());
2297     const auto channelThreshold = 0.005f; // 1/255 < 0.005 < 2/255
2298     const tcu::Vec4 threshold(channelThreshold, channelThreshold, channelThreshold, 0.0f);
2299 
2300     if (!tcu::floatThresholdCompare(log, "Result", "", levelColors.at(static_cast<size_t>(accessedLevel)), resultAccess,
2301                                     threshold, tcu::COMPARE_LOG_EVERYTHING))
2302         return tcu::TestStatus::fail("Unexpected color found in color buffer -- check log for details");
2303 
2304     return tcu::TestStatus::pass("Pass");
2305 }
2306 
2307 } // namespace
2308 
createAllFormatsSamplerTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType,bool separateStencilUsage=false)2309 tcu::TestCaseGroup *createAllFormatsSamplerTests(tcu::TestContext &testCtx,
2310                                                  PipelineConstructionType pipelineConstructionType,
2311                                                  bool separateStencilUsage = false)
2312 {
2313     const struct
2314     {
2315         SamplerViewType type;
2316         const char *name;
2317     } imageViewTypes[] = {{VK_IMAGE_VIEW_TYPE_1D, "1d"},
2318                           {{VK_IMAGE_VIEW_TYPE_1D, false}, "1d_unnormalized"},
2319                           {VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array"},
2320                           {VK_IMAGE_VIEW_TYPE_2D, "2d"},
2321                           {{VK_IMAGE_VIEW_TYPE_2D, false}, "2d_unnormalized"},
2322                           {VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array"},
2323                           {VK_IMAGE_VIEW_TYPE_3D, "3d"},
2324                           {VK_IMAGE_VIEW_TYPE_CUBE, "cube"},
2325                           {VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array"}};
2326 
2327     const VkFormat formats[] = {
2328         // Packed formats
2329         VK_FORMAT_R4G4_UNORM_PACK8,
2330         VK_FORMAT_R4G4B4A4_UNORM_PACK16,
2331         VK_FORMAT_R5G6B5_UNORM_PACK16,
2332         VK_FORMAT_R5G5B5A1_UNORM_PACK16,
2333         VK_FORMAT_A2B10G10R10_UNORM_PACK32,
2334         VK_FORMAT_A2R10G10B10_UINT_PACK32,
2335         VK_FORMAT_B10G11R11_UFLOAT_PACK32,
2336         VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
2337         VK_FORMAT_B4G4R4A4_UNORM_PACK16,
2338         VK_FORMAT_B5G5R5A1_UNORM_PACK16,
2339         VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,
2340         VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,
2341 #ifndef CTS_USES_VULKANSC
2342         VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR,
2343 #endif // CTS_USES_VULKANSC
2344 
2345         // Pairwise combinations of 8-bit channel formats, UNORM/SNORM/SINT/UINT/SRGB type x 1-to-4 channels x RGBA/BGRA order
2346         VK_FORMAT_R8_SRGB,
2347         VK_FORMAT_R8G8B8_UINT,
2348         VK_FORMAT_B8G8R8A8_SINT,
2349         VK_FORMAT_R8G8_UNORM,
2350         VK_FORMAT_B8G8R8_SNORM,
2351         VK_FORMAT_R8G8B8A8_SNORM,
2352         VK_FORMAT_R8G8_UINT,
2353         VK_FORMAT_R8_SINT,
2354         VK_FORMAT_R8G8B8A8_SRGB,
2355         VK_FORMAT_R8G8B8A8_UNORM,
2356         VK_FORMAT_B8G8R8A8_UNORM,
2357         VK_FORMAT_B8G8R8_SRGB,
2358         VK_FORMAT_R8G8_SRGB,
2359         VK_FORMAT_R8_UINT,
2360         VK_FORMAT_R8G8B8A8_UINT,
2361         VK_FORMAT_R8G8_SINT,
2362         VK_FORMAT_R8_SNORM,
2363         VK_FORMAT_B8G8R8_SINT,
2364         VK_FORMAT_R8G8_SNORM,
2365         VK_FORMAT_B8G8R8_UNORM,
2366         VK_FORMAT_R8_UNORM,
2367 #ifndef CTS_USES_VULKANSC
2368         VK_FORMAT_A8_UNORM_KHR,
2369 #endif // CTS_USES_VULKANSC
2370 
2371         // Pairwise combinations of 16/32-bit channel formats x SINT/UINT/SFLOAT type x 1-to-4 channels
2372         VK_FORMAT_R32G32_SFLOAT,
2373         VK_FORMAT_R32G32B32_UINT,
2374         VK_FORMAT_R16G16B16A16_SFLOAT,
2375         VK_FORMAT_R16G16_UINT,
2376         VK_FORMAT_R32G32B32A32_SINT,
2377         VK_FORMAT_R16G16B16_SINT,
2378         VK_FORMAT_R16_SFLOAT,
2379         VK_FORMAT_R32_SINT,
2380         VK_FORMAT_R32_UINT,
2381         VK_FORMAT_R16G16B16_SFLOAT,
2382         VK_FORMAT_R16G16_SINT,
2383 
2384         // More 16/32-bit formats required for testing VK_EXT_sampler_filter_minmax
2385         VK_FORMAT_R16_SNORM,
2386         VK_FORMAT_R32_SFLOAT,
2387 
2388         // Scaled formats
2389         VK_FORMAT_R8G8B8A8_SSCALED,
2390         VK_FORMAT_A2R10G10B10_USCALED_PACK32,
2391 
2392         // Compressed formats
2393         VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,
2394         VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,
2395         VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,
2396         VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,
2397         VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,
2398         VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,
2399         VK_FORMAT_EAC_R11_UNORM_BLOCK,
2400         VK_FORMAT_EAC_R11_SNORM_BLOCK,
2401         VK_FORMAT_EAC_R11G11_UNORM_BLOCK,
2402         VK_FORMAT_EAC_R11G11_SNORM_BLOCK,
2403         VK_FORMAT_ASTC_4x4_UNORM_BLOCK,
2404         VK_FORMAT_ASTC_5x4_SRGB_BLOCK,
2405         VK_FORMAT_ASTC_6x5_UNORM_BLOCK,
2406         VK_FORMAT_ASTC_6x6_SRGB_BLOCK,
2407         VK_FORMAT_ASTC_8x6_UNORM_BLOCK,
2408         VK_FORMAT_ASTC_8x8_SRGB_BLOCK,
2409         VK_FORMAT_ASTC_10x6_UNORM_BLOCK,
2410         VK_FORMAT_ASTC_10x8_SRGB_BLOCK,
2411         VK_FORMAT_ASTC_12x10_UNORM_BLOCK,
2412         VK_FORMAT_ASTC_12x12_SRGB_BLOCK,
2413 
2414         // Depth formats required for testing VK_EXT_sampler_filter_minmax
2415         VK_FORMAT_D16_UNORM,
2416         VK_FORMAT_X8_D24_UNORM_PACK32,
2417         VK_FORMAT_D32_SFLOAT,
2418         VK_FORMAT_D16_UNORM_S8_UINT,
2419         VK_FORMAT_D24_UNORM_S8_UINT,
2420         VK_FORMAT_D32_SFLOAT_S8_UINT,
2421     };
2422 
2423     de::MovePtr<tcu::TestCaseGroup> viewTypeTests(new tcu::TestCaseGroup(testCtx, "view_type"));
2424 
2425     for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++)
2426     {
2427         const SamplerViewType viewType = imageViewTypes[viewTypeNdx].type;
2428         de::MovePtr<tcu::TestCaseGroup> viewTypeGroup(
2429             new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name));
2430         de::MovePtr<tcu::TestCaseGroup> formatTests(new tcu::TestCaseGroup(testCtx, "format"));
2431 
2432         for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
2433         {
2434             const VkFormat format     = formats[formatNdx];
2435             const bool isCompressed   = isCompressedFormat(format);
2436             const bool isDepthStencil = !isCompressed && tcu::hasDepthComponent(mapVkFormat(format).order) &&
2437                                         tcu::hasStencilComponent(mapVkFormat(format).order);
2438             if (isCompressed)
2439             {
2440                 // Do not use compressed formats with 1D and 1D array textures.
2441                 if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY)
2442                     break;
2443             }
2444 
2445             if (separateStencilUsage && !isDepthStencil)
2446                 continue;
2447 
2448             de::MovePtr<tcu::TestCaseGroup> formatGroup(
2449                 new tcu::TestCaseGroup(testCtx, getFormatCaseName(format).c_str()));
2450 
2451             if (!isCompressed && viewType.isNormalized())
2452             {
2453                 // Do not include minFilter tests with compressed formats.
2454                 // Randomly generated compressed textures are too noisy and will derive in false positives.
2455                 de::MovePtr<tcu::TestCaseGroup> minFilterTests = createSamplerMinFilterTests(
2456                     testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2457                 de::MovePtr<tcu::TestCaseGroup> minReduceFilterTests = createSamplerMinReduceFilterTests(
2458                     testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2459                 formatGroup->addChild(minFilterTests.release());
2460                 formatGroup->addChild(minReduceFilterTests.release());
2461             }
2462 
2463             de::MovePtr<tcu::TestCaseGroup> magFilterTests =
2464                 createSamplerMagFilterTests(testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2465             formatGroup->addChild(magFilterTests.release());
2466 
2467             if (viewType.isNormalized())
2468             {
2469                 de::MovePtr<tcu::TestCaseGroup> magReduceFilterTests = createSamplerMagReduceFilterTests(
2470                     testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2471                 de::MovePtr<tcu::TestCaseGroup> mipmapTests =
2472                     createSamplerMipmapTests(testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2473 
2474                 formatGroup->addChild(magReduceFilterTests.release());
2475                 formatGroup->addChild(mipmapTests.release());
2476             }
2477 
2478             if (viewType != VK_IMAGE_VIEW_TYPE_CUBE && viewType != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY)
2479             {
2480                 de::MovePtr<tcu::TestCaseGroup> addressModesTests = createSamplerAddressModesTests(
2481                     testCtx, pipelineConstructionType, viewType, format, separateStencilUsage);
2482                 formatGroup->addChild(addressModesTests.release());
2483             }
2484 
2485             formatTests->addChild(formatGroup.release());
2486         }
2487 
2488         viewTypeGroup->addChild(formatTests.release());
2489         viewTypeTests->addChild(viewTypeGroup.release());
2490     }
2491 
2492     return viewTypeTests.release();
2493 }
2494 
createExactSamplingTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)2495 tcu::TestCaseGroup *createExactSamplingTests(tcu::TestContext &testCtx,
2496                                              PipelineConstructionType pipelineConstructionType)
2497 {
2498     de::MovePtr<tcu::TestCaseGroup> exactSamplingTests(new tcu::TestCaseGroup(testCtx, "exact_sampling"));
2499 
2500     static const std::vector<vk::VkFormat> formats = {
2501         vk::VK_FORMAT_R8_SRGB,          vk::VK_FORMAT_R8G8B8_UINT,       vk::VK_FORMAT_B8G8R8A8_SINT,
2502         vk::VK_FORMAT_R8G8_UNORM,       vk::VK_FORMAT_B8G8R8_SNORM,      vk::VK_FORMAT_R8G8B8A8_SNORM,
2503         vk::VK_FORMAT_R8G8_UINT,        vk::VK_FORMAT_R8_SINT,           vk::VK_FORMAT_R8G8B8A8_SRGB,
2504         vk::VK_FORMAT_R8G8B8A8_UNORM,   vk::VK_FORMAT_B8G8R8A8_UNORM,    vk::VK_FORMAT_B8G8R8_SRGB,
2505         vk::VK_FORMAT_R8G8_SRGB,        vk::VK_FORMAT_R8_UINT,           vk::VK_FORMAT_R8G8B8A8_UINT,
2506         vk::VK_FORMAT_R8G8_SINT,        vk::VK_FORMAT_R8_SNORM,          vk::VK_FORMAT_B8G8R8_SINT,
2507         vk::VK_FORMAT_R8G8_SNORM,       vk::VK_FORMAT_B8G8R8_UNORM,      vk::VK_FORMAT_R8_UNORM,
2508 #ifndef CTS_USES_VULKANSC
2509         vk::VK_FORMAT_A8_UNORM_KHR,
2510 #endif // CTS_USES_VULKANSC
2511 
2512         vk::VK_FORMAT_R32G32_SFLOAT,    vk::VK_FORMAT_R32G32B32_UINT,    vk::VK_FORMAT_R16G16B16A16_SFLOAT,
2513         vk::VK_FORMAT_R16G16_UINT,      vk::VK_FORMAT_R32G32B32A32_SINT, vk::VK_FORMAT_R16G16B16_SINT,
2514         vk::VK_FORMAT_R16_SFLOAT,       vk::VK_FORMAT_R32_SINT,          vk::VK_FORMAT_R32_UINT,
2515         vk::VK_FORMAT_R16G16B16_SFLOAT, vk::VK_FORMAT_R16G16_SINT,
2516 
2517         vk::VK_FORMAT_R16_SNORM,        vk::VK_FORMAT_R32_SFLOAT,
2518     };
2519 
2520     static const struct
2521     {
2522         const bool unnormalized;
2523         const std::string name;
2524     } unnormalizedCoordinates[] = {
2525         // Normalized coordinates
2526         {false, "normalized_coords"},
2527         // Unnormalized coordinates
2528         {true, "unnormalized_coords"},
2529     };
2530 
2531     static const struct
2532     {
2533         const tcu::Maybe<float> offset;
2534         const std::string name;
2535     } testEdges[] = {
2536         // Sampling points centered in texel
2537         {tcu::Nothing, "centered"},
2538         // Sampling points near left edge
2539         {tcu::just<float>(-1.0f), "edge_left"},
2540         // Sampling points near right edge
2541         {tcu::just<float>(+1.0f), "edge_right"},
2542     };
2543 
2544     static const std::vector<std::pair<bool, std::string>> solidColor = {
2545         {false, "gradient"},
2546         {true, "solid_color"},
2547     };
2548 
2549     for (const auto format : formats)
2550     {
2551         const std::string formatName = getFormatCaseName(format);
2552 
2553         de::MovePtr<tcu::TestCaseGroup> formatGroup(new tcu::TestCaseGroup(testCtx, formatName.c_str()));
2554 
2555         for (const auto &solid : solidColor)
2556         {
2557             de::MovePtr<tcu::TestCaseGroup> solidColorGroup(new tcu::TestCaseGroup(testCtx, solid.second.c_str()));
2558 
2559             for (int unIdx = 0; unIdx < DE_LENGTH_OF_ARRAY(unnormalizedCoordinates); ++unIdx)
2560             {
2561                 const auto &unnorm = unnormalizedCoordinates[unIdx];
2562                 de::MovePtr<tcu::TestCaseGroup> coordGroup(new tcu::TestCaseGroup(testCtx, unnorm.name.c_str()));
2563 
2564                 for (int edgeIdx = 0; edgeIdx < DE_LENGTH_OF_ARRAY(testEdges); ++edgeIdx)
2565                 {
2566                     const auto &edges                      = testEdges[edgeIdx];
2567                     const ExactSamplingCase::Params params = {pipelineConstructionType, format, unnorm.unnormalized,
2568                                                               solid.first, edges.offset};
2569                     coordGroup->addChild(new ExactSamplingCase{testCtx, edges.name, params});
2570                 }
2571 
2572                 solidColorGroup->addChild(coordGroup.release());
2573             }
2574 
2575             formatGroup->addChild(solidColorGroup.release());
2576         }
2577 
2578         exactSamplingTests->addChild(formatGroup.release());
2579     }
2580 
2581     return exactSamplingTests.release();
2582 }
2583 
createMaxSamplerLodBiasTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)2584 tcu::TestCaseGroup *createMaxSamplerLodBiasTests(tcu::TestContext &testCtx,
2585                                                  PipelineConstructionType pipelineConstructionType)
2586 {
2587     de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "max_sampler_lod_bias"));
2588 
2589     for (int caseIdx = 0; caseIdx < static_cast<int>(LodBiasCase::CASE_COUNT); ++caseIdx)
2590     {
2591         const auto caseValue = static_cast<LodBiasCase>(caseIdx);
2592         const auto testName  = getLodBiasCaseName(caseValue);
2593         const MaxSamplerLodBiasParams params{pipelineConstructionType, caseValue};
2594 
2595 #ifdef CTS_USES_VULKANSC
2596         if (caseValue == LodBiasCase::VIEW_MINLOD)
2597             continue;
2598 #endif // CTS_USES_VULKANSC
2599 
2600         testGroup->addChild(new MaxSamplerLodBiasCase(testCtx, testName, params));
2601     }
2602 
2603     return testGroup.release();
2604 }
2605 
createSamplerTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)2606 tcu::TestCaseGroup *createSamplerTests(tcu::TestContext &testCtx, PipelineConstructionType pipelineConstructionType)
2607 {
2608     const auto genAllTests = (pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC ||
2609                               pipelineConstructionType == vk::PIPELINE_CONSTRUCTION_TYPE_SHADER_OBJECT_UNLINKED_SPIRV);
2610 
2611     de::MovePtr<tcu::TestCaseGroup> samplerTests(new tcu::TestCaseGroup(testCtx, "sampler"));
2612     {
2613         if (genAllTests)
2614             samplerTests->addChild(createAllFormatsSamplerTests(testCtx, pipelineConstructionType));
2615         samplerTests->addChild(createExactSamplingTests(testCtx, pipelineConstructionType));
2616     }
2617 
2618     // tests for VK_EXT_separate_stencil_usage
2619     de::MovePtr<tcu::TestCaseGroup> separateStencilUsageSamplerTests(
2620         new tcu::TestCaseGroup(testCtx, "separate_stencil_usage"));
2621     {
2622         separateStencilUsageSamplerTests->addChild(
2623             createAllFormatsSamplerTests(testCtx, pipelineConstructionType, true));
2624         samplerTests->addChild(separateStencilUsageSamplerTests.release());
2625     }
2626 
2627 #ifndef CTS_USES_VULKANSC
2628     // Border color swizzle tests.
2629     if (genAllTests)
2630         samplerTests->addChild(createSamplerBorderSwizzleTests(testCtx, pipelineConstructionType));
2631 #endif // CTS_USES_VULKANSC
2632 
2633     samplerTests->addChild(createMaxSamplerLodBiasTests(testCtx, pipelineConstructionType));
2634 
2635     return samplerTests.release();
2636 }
2637 
2638 } // namespace pipeline
2639 } // namespace vkt
2640