Half-float texture interpolation tolerance is too small.
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / texture / vktTextureFilteringExplicitLodTests.cpp
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2016 Google Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Texture filtering tests with explicit LOD instructions
22  *//*--------------------------------------------------------------------*/
23
24 #include "vktTextureFilteringExplicitLodTests.hpp"
25
26 #include "vkDefs.hpp"
27
28 #include "vktSampleVerifier.hpp"
29 #include "vktShaderExecutor.hpp"
30 #include "vktTestCaseUtil.hpp"
31
32 #include "vkDeviceUtil.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkPlatform.hpp"
35 #include "vkRef.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkStrUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkQueryUtil.hpp"
40 #include "vkMemUtil.hpp"
41 #include "vkCmdUtil.hpp"
42
43 #include "tcuTexLookupVerifier.hpp"
44 #include "tcuTestLog.hpp"
45 #include "tcuTexture.hpp"
46 #include "tcuTextureUtil.hpp"
47 #include "tcuVector.hpp"
48
49 #include "deClock.h"
50 #include "deMath.h"
51 #include "deStringUtil.hpp"
52 #include "deUniquePtr.hpp"
53 #include "deSharedPtr.hpp"
54
55 #include <sstream>
56 #include <string>
57 #include <vector>
58
59 namespace vkt
60 {
61 namespace texture
62 {
63
64 using namespace tcu;
65 using namespace vk;
66 using std::string;
67
68 namespace
69 {
70
71 std::vector<de::SharedPtr<tcu::FloatFormat>> getPrecision (VkFormat format, int fpPrecisionDelta)
72 {
73         std::vector<de::SharedPtr<tcu::FloatFormat>>    floatFormats;
74         de::SharedPtr<tcu::FloatFormat>                                 fp16                    (new tcu::FloatFormat(-14, 15, std::max(0, 10 + fpPrecisionDelta), false, tcu::YES));
75         de::SharedPtr<tcu::FloatFormat>                                 fp32                    (new tcu::FloatFormat(-126, 127, std::max(0, 23 + fpPrecisionDelta), true));
76         const tcu::TextureFormat                                                tcuFormat               = mapVkFormat(format);
77         const tcu::TextureChannelClass                                  channelClass    = tcu::getTextureChannelClass(tcuFormat.type);
78         const tcu::IVec4                                                                channelDepth    = tcu::getTextureFormatBitDepth(tcuFormat);
79
80         for (int channelIdx = 0; channelIdx < 4; channelIdx++)
81         {
82                 switch(channelClass)
83                 {
84                         case TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
85                                 floatFormats.push_back(de::SharedPtr<tcu::FloatFormat>(new tcu::NormalizedFormat(std::max(0,channelDepth[channelIdx] + fpPrecisionDelta - 1))));
86                                 break;
87
88                         case TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
89                                 floatFormats.push_back(de::SharedPtr<tcu::FloatFormat>(new tcu::NormalizedFormat(std::max(0,channelDepth[channelIdx] + fpPrecisionDelta))));
90                                 break;
91
92                         case TEXTURECHANNELCLASS_FLOATING_POINT:
93                                 if (channelDepth[channelIdx] == 16)
94                                 {
95                                         floatFormats.push_back(fp16);
96                                 }
97                                 else
98                                 {
99                                         DE_ASSERT(channelDepth[channelIdx] == 32 || channelDepth[channelIdx] == 0);
100                                         floatFormats.push_back(fp32);
101                                 }
102                                 break;
103
104                         default:
105                                 DE_FATAL("Unexpected channel class.");
106                         break;
107                 };
108         }
109
110         return floatFormats;
111 }
112
113 using namespace shaderexecutor;
114
115 string genSamplerDeclaration(const ImageViewParameters& imParams,
116                                                          const SamplerParameters&       samplerParams)
117 {
118         string result = "sampler";
119
120         switch (imParams.dim)
121         {
122                 case IMG_DIM_1D:
123                         result += "1D";
124                         break;
125
126                 case IMG_DIM_2D:
127                         result += "2D";
128                         break;
129
130                 case IMG_DIM_3D:
131                         result += "3D";
132                         break;
133
134                 case IMG_DIM_CUBE:
135                         result += "Cube";
136                         break;
137
138                 default:
139                         break;
140         }
141
142         if (imParams.isArrayed)
143         {
144                 result += "Array";
145         }
146
147         if (samplerParams.isCompare)
148         {
149                 result += "Shadow";
150         }
151
152         return result;
153 }
154
155 string genLookupCode(const ImageViewParameters&         imParams,
156                                          const SamplerParameters&               samplerParams,
157                                          const SampleLookupSettings&    lookupSettings)
158 {
159         int dim = -1;
160
161         switch (imParams.dim)
162         {
163                 case IMG_DIM_1D:
164                         dim = 1;
165                         break;
166
167                 case IMG_DIM_2D:
168                         dim = 2;
169                         break;
170
171                 case IMG_DIM_3D:
172                         dim = 3;
173                         break;
174
175                 case IMG_DIM_CUBE:
176                         dim = 3;
177                         break;
178
179                 default:
180                         dim = 0;
181                         break;
182         }
183
184         DE_ASSERT(dim >= 1 && dim <= 3);
185
186         int numCoordComp = dim;
187
188         if (lookupSettings.isProjective)
189         {
190                 ++numCoordComp;
191         }
192
193         int numArgComp = numCoordComp;
194         bool hasSeparateCompare = false;
195
196         if (imParams.isArrayed)
197         {
198                 DE_ASSERT(!lookupSettings.isProjective && "Can't do a projective lookup on an arrayed image!");
199
200                 ++numArgComp;
201         }
202
203         if (samplerParams.isCompare && numCoordComp == 4)
204         {
205                 hasSeparateCompare = true;
206         }
207         else if (samplerParams.isCompare)
208         {
209                 ++numArgComp;
210         }
211
212         // Build coordinate input to texture*() function
213
214         string arg      = "vec";
215         arg += (char) (numArgComp + '0');
216         arg += "(vec";
217         arg += (char) (numCoordComp + '0');
218         arg += "(coord)";
219
220     int numZero = numArgComp - numCoordComp;
221
222         if (imParams.isArrayed)
223         {
224                 arg += ", layer";
225                 --numZero;
226         }
227
228         if (samplerParams.isCompare && !hasSeparateCompare)
229         {
230                 arg += ", dRef";
231                 --numZero;
232         }
233
234         for (int ndx = 0; ndx < numZero; ++ndx)
235         {
236                 arg += ", 0.0";
237         }
238
239         arg += ")";
240
241         // Build call to texture*() function
242
243         string code;
244
245         code += "result = texture";
246
247         if (lookupSettings.isProjective)
248         {
249                 code += "Proj";
250         }
251
252         if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
253         {
254                 code += "Grad";
255         }
256         else if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_LOD)
257         {
258                 code += "Lod";
259         }
260
261         code += "(testSampler, ";
262         code += arg;
263
264         if (samplerParams.isCompare && hasSeparateCompare)
265         {
266                 code += ", dRef";
267         }
268
269         if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
270         {
271                 code += ", vec";
272                 code += (char) (numCoordComp + '0');
273                 code += "(dPdx), ";
274                 code += "vec";
275                 code += (char) (numCoordComp + '0');
276                 code += "(dPdy)";
277         }
278         else if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_LOD)
279         {
280                 code += ", lod";
281         }
282
283         code += ");";
284
285         return code;
286 }
287
288 void initializeImage(Context& ctx, VkImage im, const ConstPixelBufferAccess* pba, ImageViewParameters imParams)
289 {
290         const DeviceInterface& vkd = ctx.getDeviceInterface();
291         const VkDevice dev = ctx.getDevice();
292         const deUint32 uqfi = ctx.getUniversalQueueFamilyIndex();
293
294         const VkDeviceSize bufSize =
295                 getPixelSize(mapVkFormat(imParams.format))
296                 * imParams.arrayLayers
297                 * imParams.size[0]
298                 * imParams.size[1]
299                 * imParams.size[2]
300                 * 2;
301
302     const VkBufferCreateInfo bufCreateInfo =
303         {
304                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // sType
305                 DE_NULL,                                                                // pNext
306                 0,                                                                              // flags
307                 bufSize,                                                                // size
308                 VK_BUFFER_USAGE_TRANSFER_SRC_BIT,               // usage
309                 VK_SHARING_MODE_EXCLUSIVE,                              // sharingMode
310                 1,                                                                              // queueFamilyIndexCount
311                 &uqfi                                                                   // pQueueFamilyIndices
312         };
313
314         Unique<VkBuffer> buf(createBuffer(vkd, dev, &bufCreateInfo));
315
316         VkMemoryRequirements bufMemReq;
317         vkd.getBufferMemoryRequirements(dev, buf.get(), &bufMemReq);
318
319         de::UniquePtr<Allocation> bufMem(ctx.getDefaultAllocator().allocate(bufMemReq, MemoryRequirement::HostVisible));
320         VK_CHECK(vkd.bindBufferMemory(dev, buf.get(), bufMem->getMemory(), bufMem->getOffset()));
321
322         std::vector<VkBufferImageCopy> copyRegions;
323
324         deUint8* const bufMapPtr = reinterpret_cast<deUint8*>(bufMem->getHostPtr());
325         deUint8* bufCurPtr = bufMapPtr;
326
327         for (int level = 0; level < imParams.levels; ++level)
328         {
329                 const IVec3 curLevelSize = pba[level].getSize();
330
331                 const std::size_t copySize =
332                         getPixelSize(mapVkFormat(imParams.format))
333                         * curLevelSize[0] * curLevelSize[1] * curLevelSize[2]
334                         * imParams.arrayLayers;
335
336                 deMemcpy(bufCurPtr, pba[level].getDataPtr(), copySize);
337
338                 const VkImageSubresourceLayers curSubresource =
339                 {
340                         VK_IMAGE_ASPECT_COLOR_BIT,
341                         (deUint32)level,
342                         0,
343                         (deUint32)imParams.arrayLayers
344                 };
345
346                 const VkBufferImageCopy curRegion =
347                 {
348                         (VkDeviceSize) (bufCurPtr - bufMapPtr),
349                         0,
350                         0,
351                         curSubresource,
352                         {0U, 0U, 0U},
353                         {(deUint32)curLevelSize[0], (deUint32)curLevelSize[1], (deUint32)curLevelSize[2]}
354                 };
355
356                 copyRegions.push_back(curRegion);
357
358                 bufCurPtr += copySize;
359         }
360
361         flushAlloc(vkd, dev, *bufMem);
362
363         copyBufferToImage(vkd, dev, ctx.getUniversalQueue(), ctx.getUniversalQueueFamilyIndex(), buf.get(), bufSize, copyRegions, DE_NULL, VK_IMAGE_ASPECT_COLOR_BIT, imParams.levels, imParams.arrayLayers, im);
364 }
365
366 struct TestCaseData
367 {
368         std::vector<ConstPixelBufferAccess>     pba;
369         ImageViewParameters                                     imParams;
370         SamplerParameters                                       samplerParams;
371         SampleLookupSettings                            sampleLookupSettings;
372         glu::ShaderType                                         shaderType;
373 };
374
375 VkSamplerCreateInfo mapSamplerCreateInfo (const SamplerParameters& samplerParams)
376 {
377         VkSamplerCreateInfo samplerCreateInfo =
378         {
379                 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,                          // sType
380                 DE_NULL,                                                                                        // pNext
381                 0U,                                                                                                     // flags
382             samplerParams.magFilter,                                                    // magFilter
383                 samplerParams.minFilter,                                                        // minFilter
384                 samplerParams.mipmapFilter,                                                     // mipmapMode
385             samplerParams.wrappingModeU,                                                // addressModeU
386             samplerParams.wrappingModeV,                                                // addressModeV
387             samplerParams.wrappingModeW,                                                // addressMoveW
388                 samplerParams.lodBias,                                                          // mipLodBias
389                 VK_FALSE,                                                                                       // anisotropyEnable
390                 1.0f,                                                                                           // maxAnisotropy
391                 VK_FALSE,                                                                                       // compareEnable
392                 VK_COMPARE_OP_NEVER,                                                            // compareOp
393                 samplerParams.minLod,                                                           // minLod
394                 samplerParams.maxLod,                                                           // maxLod
395             samplerParams.borderColor,                                                  // borderColor
396                 samplerParams.isUnnormalized ? VK_TRUE : VK_FALSE,      // unnormalizedCoordinates
397         };
398
399         if (samplerParams.isCompare)
400         {
401                 samplerCreateInfo.compareEnable = VK_TRUE;
402
403             DE_FATAL("Not implemented");
404         }
405
406         return samplerCreateInfo;
407 }
408
409 VkImageType mapImageType (ImgDim dim)
410 {
411         VkImageType imType;
412
413         switch (dim)
414         {
415                 case IMG_DIM_1D:
416                         imType = VK_IMAGE_TYPE_1D;
417                         break;
418
419                 case IMG_DIM_2D:
420                 case IMG_DIM_CUBE:
421                         imType = VK_IMAGE_TYPE_2D;
422                         break;
423
424                 case IMG_DIM_3D:
425                         imType = VK_IMAGE_TYPE_3D;
426                         break;
427
428                 default:
429                         imType = VK_IMAGE_TYPE_LAST;
430                         break;
431         }
432
433         return imType;
434 }
435
436 VkImageViewType mapImageViewType (const ImageViewParameters& imParams)
437 {
438         VkImageViewType imViewType;
439
440         if (imParams.isArrayed)
441         {
442                 switch (imParams.dim)
443                 {
444                         case IMG_DIM_1D:
445                                 imViewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
446                                 break;
447
448                         case IMG_DIM_2D:
449                                 imViewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
450                                 break;
451
452                         case IMG_DIM_CUBE:
453                                 imViewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
454                                 break;
455
456                         default:
457                                 imViewType = VK_IMAGE_VIEW_TYPE_LAST;
458                                 break;
459                 }
460         }
461         else
462         {
463                 switch (imParams.dim)
464                 {
465                         case IMG_DIM_1D:
466                                 imViewType = VK_IMAGE_VIEW_TYPE_1D;
467                                 break;
468
469                         case IMG_DIM_2D:
470                                 imViewType = VK_IMAGE_VIEW_TYPE_2D;
471                                 break;
472
473                         case IMG_DIM_3D:
474                                 imViewType = VK_IMAGE_VIEW_TYPE_3D;
475                                 break;
476
477                         case IMG_DIM_CUBE:
478                                 imViewType = VK_IMAGE_VIEW_TYPE_CUBE;
479                                 break;
480
481                         default:
482                                 imViewType = VK_IMAGE_VIEW_TYPE_LAST;
483                                 break;
484                 }
485         }
486
487         return imViewType;
488 }
489
490 class DataGenerator
491 {
492 public:
493         virtual                                                                         ~DataGenerator  (void) {}
494
495         virtual bool                                                            generate                (void) = 0;
496
497         virtual std::vector<ConstPixelBufferAccess> getPba                      (void) const = 0;
498         virtual std::vector<SampleArguments>            getSampleArgs   (void) const = 0;
499
500 protected:
501                                                                                                 DataGenerator   (void) {}
502 };
503
504 class TextureFilteringTestInstance : public TestInstance
505 {
506 public:
507                                                                                 TextureFilteringTestInstance    (Context&                                       ctx,
508                                                                                                                                                  const TestCaseData&            testCaseData,
509                                                                                                                                                  const ShaderSpec&                      shaderSpec,
510                                                                                                                                                  de::MovePtr<DataGenerator>     gen);
511
512         virtual TestStatus                                      iterate                                                 (void) { return runTest(); }
513
514 protected:
515         TestStatus                                                      runTest                                                 (void);
516         bool                                                            isSupported                                             (void);
517         void                                                            createResources                                 (void);
518         void                                                            execute                                                 (void);
519         TestStatus                                                      verify                                                  (void);
520
521         tcu::Sampler                                            mapTcuSampler                                   (void) const;
522
523         const glu::ShaderType                           m_shaderType;
524         const ShaderSpec                                        m_shaderSpec;
525         const ImageViewParameters                       m_imParams;
526         const SamplerParameters                         m_samplerParams;
527         const SampleLookupSettings                      m_sampleLookupSettings;
528
529         std::vector<SampleArguments>            m_sampleArguments;
530         deUint32                                                        m_numSamples;
531
532         de::MovePtr<Allocation>                         m_imAllocation;
533         Move<VkImage>                                           m_im;
534         Move<VkImageView>                                       m_imView;
535         Move<VkSampler>                                         m_sampler;
536
537         Move<VkDescriptorSetLayout>                     m_extraResourcesLayout;
538         Move<VkDescriptorPool>                          m_extraResourcesPool;
539         Move<VkDescriptorSet>                           m_extraResourcesSet;
540
541         de::MovePtr<ShaderExecutor>                     m_executor;
542
543         std::vector<ConstPixelBufferAccess> m_levels;
544         de::MovePtr<DataGenerator>                      m_gen;
545
546         std::vector<Vec4>                                       m_resultSamples;
547         std::vector<Vec4>                                       m_resultCoords;
548 };
549
550 TextureFilteringTestInstance::TextureFilteringTestInstance (Context&                                    ctx,
551                                                                                                                         const TestCaseData&                     testCaseData,
552                                                                                                                         const ShaderSpec&                       shaderSpec,
553                                                                                                                         de::MovePtr<DataGenerator>      gen)
554         : TestInstance                          (ctx)
555         , m_shaderType                          (testCaseData.shaderType)
556         , m_shaderSpec                          (shaderSpec)
557         , m_imParams                            (testCaseData.imParams)
558         , m_samplerParams                       (testCaseData.samplerParams)
559         , m_sampleLookupSettings        (testCaseData.sampleLookupSettings)
560         , m_levels                                      (testCaseData.pba)
561         , m_gen                                         (gen.release())
562 {
563         for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
564                 DE_ASSERT(m_imParams.size[compNdx] > 0);
565 }
566
567 TestStatus TextureFilteringTestInstance::runTest (void)
568 {
569         if (!isSupported())
570             TCU_THROW(NotSupportedError, "Unsupported combination of filtering and image format");
571
572         TCU_CHECK(m_gen->generate());
573         m_levels = m_gen->getPba();
574
575         m_sampleArguments = m_gen->getSampleArgs();
576         m_numSamples = (deUint32)m_sampleArguments.size();
577
578         createResources();
579         initializeImage(m_context, m_im.get(), &m_levels[0], m_imParams);
580
581         deUint64 startTime, endTime;
582
583         startTime = deGetMicroseconds();
584         execute();
585         endTime = deGetMicroseconds();
586
587         m_context.getTestContext().getLog() << TestLog::Message
588                                                                                 << "Execution time: "
589                                                                                 << endTime - startTime
590                                                                                 << "us"
591                                                                                 << TestLog::EndMessage;
592
593     startTime = deGetMicroseconds();
594         TestStatus result = verify();
595     endTime = deGetMicroseconds();
596
597         m_context.getTestContext().getLog() << TestLog::Message
598                                                                                 << "Verification time: "
599                                                                                 << endTime - startTime
600                                                                                 << "us"
601                                                                                 << TestLog::EndMessage;
602
603         return result;
604 }
605
606 TestStatus TextureFilteringTestInstance::verify (void)
607 {
608         // \todo [2016-06-24 collinbaker] Handle cubemaps
609
610         const int                                                                               coordBits                       = (int)m_context.getDeviceProperties().limits.subTexelPrecisionBits;
611         const int                                                                               mipmapBits                      = (int)m_context.getDeviceProperties().limits.mipmapPrecisionBits;
612         const int                                                                               maxPrintedFailures      = 5;
613         int                                                                                             failCount                       = 0;
614         int                                                                                             warningCount            = 0;
615         const tcu::TextureFormat                                                tcuFormat                       = mapVkFormat(m_imParams.format);
616         std::vector<de::SharedPtr<tcu::FloatFormat>>    strictPrecision         = getPrecision(m_imParams.format, 0);
617         std::vector<de::SharedPtr<tcu::FloatFormat>>    relaxedPrecision        = tcuFormat.type == tcu::TextureFormat::HALF_FLOAT ? getPrecision(m_imParams.format, -6) : getPrecision(m_imParams.format, -2);
618         const bool                                                                              allowRelaxedPrecision   = (tcuFormat.type == tcu::TextureFormat::HALF_FLOAT || tcuFormat.type == tcu::TextureFormat::SNORM_INT8) &&
619                 (m_samplerParams.minFilter == VK_FILTER_LINEAR || m_samplerParams.magFilter == VK_FILTER_LINEAR);
620
621         const SampleVerifier                    verifier                        (m_imParams,
622                                                                                                                  m_samplerParams,
623                                                                                                                  m_sampleLookupSettings,
624                                                                                                                  coordBits,
625                                                                                                                  mipmapBits,
626                                                                                                                  strictPrecision,
627                                                                                                                  strictPrecision,
628                                                                                                                  m_levels);
629
630         const SampleVerifier                    relaxedVerifier         (m_imParams,
631                                                                                                                  m_samplerParams,
632                                                                                                                  m_sampleLookupSettings,
633                                                                                                                  coordBits,
634                                                                                                                  mipmapBits,
635                                                                                                                  strictPrecision,
636                                                                                                                  relaxedPrecision,
637                                                                                                                  m_levels);
638
639         for (deUint32 sampleNdx = 0; sampleNdx < m_numSamples; ++sampleNdx)
640         {
641                 bool compareOK = verifier.verifySample(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx]);
642                 if (compareOK)
643                         continue;
644                 if (allowRelaxedPrecision)
645                 {
646                         m_context.getTestContext().getLog()
647                                 << tcu::TestLog::Message
648                                 << "Warning: Strict validation failed, re-trying with lower precision for SNORM8 format or half float"
649                                 << tcu::TestLog::EndMessage;
650
651                         compareOK = relaxedVerifier.verifySample(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx]);
652                         if (compareOK)
653                         {
654                                 warningCount++;
655                                 continue;
656                         }
657                 }
658                 if ( failCount++ < maxPrintedFailures )
659                 {
660                         // Re-run with report logging
661                         std::string report;
662                         verifier.verifySampleReport(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx], report);
663
664                         m_context.getTestContext().getLog()
665                                 << TestLog::Section("Failed sample", "Failed sample")
666                                 << TestLog::Message
667                                 << "Sample " << sampleNdx << ".\n"
668                                 << "\tCoordinate: " << m_sampleArguments[sampleNdx].coord << "\n"
669                                 << "\tLOD: " << m_sampleArguments[sampleNdx].lod << "\n"
670                                 << "\tGPU Result: " << m_resultSamples[sampleNdx] << "\n\n"
671                                 << "Failure report:\n" << report << "\n"
672                                 << TestLog::EndMessage
673                                 << TestLog::EndSection;
674                 }
675         }
676
677         m_context.getTestContext().getLog()
678                 << TestLog::Message
679                 << "Passed " << m_numSamples - failCount << " out of " << m_numSamples << "."
680                 << TestLog::EndMessage;
681
682         if (failCount > 0)
683                 return TestStatus::fail("Verification failed");
684         else if (warningCount > 0)
685                 return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Inaccurate filtering results");
686
687         return TestStatus::pass("Success");
688 }
689
690 void TextureFilteringTestInstance::execute (void)
691 {
692         std::vector<float> coords, layers, dRefs, dPdxs, dPdys, lods;
693
694         for (deUint32 ndx = 0; ndx < m_numSamples; ++ndx)
695         {
696                 const SampleArguments& sampleArgs = m_sampleArguments[ndx];
697
698                 for (deUint8 compNdx = 0; compNdx < 4; ++compNdx)
699                 {
700                         coords.push_back(sampleArgs.coord[compNdx]);
701                         dPdxs .push_back(sampleArgs.dPdx[compNdx]);
702                         dPdys .push_back(sampleArgs.dPdy[compNdx]);
703                 }
704
705                 layers.push_back(sampleArgs.layer);
706                 dRefs .push_back(sampleArgs.dRef);
707                 lods  .push_back(sampleArgs.lod);
708         }
709
710         const void* inputs[6] =
711         {
712                 reinterpret_cast<const void*>(&coords[0]),
713                 reinterpret_cast<const void*>(&layers[0]),
714                 reinterpret_cast<const void*>(&dRefs[0]),
715                 reinterpret_cast<const void*>(&dPdxs[0]),
716                 reinterpret_cast<const void*>(&dPdys[0]),
717                 reinterpret_cast<const void*>(&lods[0])
718         };
719
720         // Staging buffers; data will be copied into vectors of Vec4
721         // \todo [2016-06-24 collinbaker] Figure out if I actually need to
722         // use staging buffers
723         std::vector<float> resultSamplesTemp(m_numSamples * 4);
724         std::vector<float> resultCoordsTemp (m_numSamples * 4);
725
726         void* outputs[2] =
727         {
728                 reinterpret_cast<void*>(&resultSamplesTemp[0]),
729                 reinterpret_cast<void*>(&resultCoordsTemp[0])
730         };
731
732         m_executor->execute(m_numSamples, inputs, outputs, *m_extraResourcesSet);
733
734         m_resultSamples.resize(m_numSamples);
735         m_resultCoords .resize(m_numSamples);
736
737         for (deUint32 ndx = 0; ndx < m_numSamples; ++ndx)
738         {
739                 m_resultSamples[ndx] = Vec4(resultSamplesTemp[4 * ndx + 0],
740                                                                         resultSamplesTemp[4 * ndx + 1],
741                                                                         resultSamplesTemp[4 * ndx + 2],
742                                                                         resultSamplesTemp[4 * ndx + 3]);
743
744                 m_resultCoords [ndx] = Vec4(resultCoordsTemp [4 * ndx + 0],
745                                                                         resultCoordsTemp [4 * ndx + 1],
746                                                                         resultCoordsTemp [4 * ndx + 2],
747                                                                         resultCoordsTemp [4 * ndx + 3]);
748         }
749 }
750
751 void TextureFilteringTestInstance::createResources (void)
752 {
753         // Create VkImage
754
755         const DeviceInterface&          vkd                             = m_context.getDeviceInterface();
756         const VkDevice                          device                  = m_context.getDevice();
757
758         const deUint32                          queueFamily             = m_context.getUniversalQueueFamilyIndex();
759         const VkImageCreateFlags        imCreateFlags   =(m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
760
761         const VkImageCreateInfo         imCreateInfo    =
762         {
763                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
764                 DE_NULL,
765                 imCreateFlags,
766             mapImageType(m_imParams.dim),
767             m_imParams.format,
768                 makeExtent3D(m_imParams.size[0], m_imParams.size[1], m_imParams.size[2]),
769             (deUint32)m_imParams.levels,
770             (deUint32)m_imParams.arrayLayers,
771                 VK_SAMPLE_COUNT_1_BIT,
772                 VK_IMAGE_TILING_OPTIMAL,
773                 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
774                 VK_SHARING_MODE_EXCLUSIVE,
775                 1,
776                 &queueFamily,
777                 VK_IMAGE_LAYOUT_UNDEFINED
778         };
779
780     m_im = createImage(vkd, device, &imCreateInfo);
781
782         // Allocate memory for image
783
784         VkMemoryRequirements imMemReq;
785         vkd.getImageMemoryRequirements(device, m_im.get(), &imMemReq);
786
787         m_imAllocation = m_context.getDefaultAllocator().allocate(imMemReq, MemoryRequirement::Any);
788         VK_CHECK(vkd.bindImageMemory(device, m_im.get(), m_imAllocation->getMemory(), m_imAllocation->getOffset()));
789
790         // Create VkImageView
791
792         // \todo [2016-06-23 collinbaker] Pick aspectMask based on image type (i.e. support depth and/or stencil images)
793         DE_ASSERT(m_imParams.dim != IMG_DIM_CUBE); // \todo Support cube maps
794         const VkImageSubresourceRange imViewSubresourceRange =
795         {
796                 VK_IMAGE_ASPECT_COLOR_BIT,                      // aspectMask
797                 0,                                                                      // baseMipLevel
798                 (deUint32)m_imParams.levels,            // levelCount
799                 0,                                                                      // baseArrayLayer
800                 (deUint32)m_imParams.arrayLayers        // layerCount
801         };
802
803         const VkComponentMapping imViewCompMap =
804         {
805                 VK_COMPONENT_SWIZZLE_R,
806                 VK_COMPONENT_SWIZZLE_G,
807                 VK_COMPONENT_SWIZZLE_B,
808                 VK_COMPONENT_SWIZZLE_A
809         };
810
811         const VkImageViewCreateInfo imViewCreateInfo =
812         {
813                 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // sType
814                 DE_NULL,                                                                        // pNext
815                 0,                                                                                      // flags
816                 m_im.get(),                                                                     // image
817                 mapImageViewType(m_imParams),                           // viewType
818             m_imParams.format,                                                  // format
819             imViewCompMap,                                                              // components
820                 imViewSubresourceRange                                          // subresourceRange
821         };
822
823         m_imView = createImageView(vkd, device, &imViewCreateInfo);
824
825         // Create VkSampler
826
827         const VkSamplerCreateInfo samplerCreateInfo = mapSamplerCreateInfo(m_samplerParams);
828         m_sampler = createSampler(vkd, device, &samplerCreateInfo);
829
830         // Create additional descriptors
831
832         {
833                 const VkDescriptorSetLayoutBinding              bindings[]      =
834                 {
835                         { 0u,   VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,      1u,             VK_SHADER_STAGE_ALL,    DE_NULL         },
836                 };
837                 const VkDescriptorSetLayoutCreateInfo   layoutInfo      =
838                 {
839                         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
840                         DE_NULL,
841                         (VkDescriptorSetLayoutCreateFlags)0u,
842                         DE_LENGTH_OF_ARRAY(bindings),
843                         bindings,
844                 };
845
846                 m_extraResourcesLayout = createDescriptorSetLayout(vkd, device, &layoutInfo);
847         }
848
849         {
850                 const VkDescriptorPoolSize                      poolSizes[]     =
851                 {
852                         { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,    1u      },
853                 };
854                 const VkDescriptorPoolCreateInfo        poolInfo        =
855                 {
856                         VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
857                         DE_NULL,
858                         (VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
859                         1u,             // maxSets
860                         DE_LENGTH_OF_ARRAY(poolSizes),
861                         poolSizes,
862                 };
863
864                 m_extraResourcesPool = createDescriptorPool(vkd, device, &poolInfo);
865         }
866
867         {
868                 const VkDescriptorSetAllocateInfo       allocInfo       =
869                 {
870                         VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
871                         DE_NULL,
872                         *m_extraResourcesPool,
873                         1u,
874                         &m_extraResourcesLayout.get(),
875                 };
876
877                 m_extraResourcesSet = allocateDescriptorSet(vkd, device, &allocInfo);
878         }
879
880         {
881                 const VkDescriptorImageInfo             imageInfo                       =
882                 {
883                         *m_sampler,
884                         *m_imView,
885                         VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
886                 };
887                 const VkWriteDescriptorSet              descriptorWrite         =
888                 {
889                         VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
890                         DE_NULL,
891                         *m_extraResourcesSet,
892                         0u,             // dstBinding
893                         0u,             // dstArrayElement
894                         1u,
895                         VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
896                         &imageInfo,
897                         (const VkDescriptorBufferInfo*)DE_NULL,
898                         (const VkBufferView*)DE_NULL,
899                 };
900
901                 vkd.updateDescriptorSets(device, 1u, &descriptorWrite, 0u, DE_NULL);
902         }
903
904         m_executor = de::MovePtr<ShaderExecutor>(createExecutor(m_context, m_shaderType, m_shaderSpec, *m_extraResourcesLayout));
905 }
906
907 VkFormatFeatureFlags getRequiredFormatFeatures (const SamplerParameters& samplerParams)
908 {
909         VkFormatFeatureFlags    features        = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
910
911         if (samplerParams.minFilter      == VK_FILTER_LINEAR ||
912                 samplerParams.magFilter  == VK_FILTER_LINEAR ||
913                 samplerParams.mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
914         {
915                 features |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
916         }
917
918         return features;
919 }
920
921 bool TextureFilteringTestInstance::isSupported (void)
922 {
923         const VkImageCreateFlags                imCreateFlags           = (m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
924         const VkFormatFeatureFlags              reqImFeatures           = getRequiredFormatFeatures(m_samplerParams);
925
926         const VkImageFormatProperties   imFormatProperties      = getPhysicalDeviceImageFormatProperties(m_context.getInstanceInterface(),
927                                                                                                                                                                                                  m_context.getPhysicalDevice(),
928                                                                                                                                                                                                  m_imParams.format,
929                                                                                                                                                                                                  mapImageType(m_imParams.dim),
930                                                                                                                                                                                                  VK_IMAGE_TILING_OPTIMAL,
931                                                                                                                                                                                                  VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
932                                                                                                                                                                                                  imCreateFlags);
933         const VkFormatProperties                formatProperties        = getPhysicalDeviceFormatProperties(m_context.getInstanceInterface(),
934                                                                                                                                                                                         m_context.getPhysicalDevice(),
935                                                                                                                                                                                         m_imParams.format);
936
937         // \todo [2016-06-23 collinbaker] Check image parameters against imFormatProperties
938         DE_UNREF(imFormatProperties);
939
940         return (formatProperties.optimalTilingFeatures & reqImFeatures) == reqImFeatures;
941 }
942
943 class TextureFilteringTestCase : public TestCase
944 {
945 public:
946         TextureFilteringTestCase (tcu::TestContext&     testCtx,
947                                                           const char*           name,
948                                                           const char*           description)
949                 : TestCase(testCtx, name, description)
950         {
951         }
952
953         void initSpec (void);
954
955         virtual void initPrograms (vk::SourceCollections& programCollection) const
956         {
957                 generateSources(m_testCaseData.shaderType, m_shaderSpec, programCollection);
958         }
959
960         virtual de::MovePtr<DataGenerator> createGenerator (void) const = 0;
961
962         virtual TestInstance* createInstance (Context& ctx) const
963         {
964                 return new TextureFilteringTestInstance(ctx, m_testCaseData, m_shaderSpec, createGenerator());
965         }
966
967 protected:
968         de::MovePtr<ShaderExecutor> m_executor;
969         TestCaseData                            m_testCaseData;
970         ShaderSpec                                      m_shaderSpec;
971 };
972
973 void TextureFilteringTestCase::initSpec (void)
974 {
975         m_shaderSpec.source = genLookupCode(m_testCaseData.imParams,
976                                                                                 m_testCaseData.samplerParams,
977                                                                                 m_testCaseData.sampleLookupSettings);
978         m_shaderSpec.source += "\nsampledCoord = coord;";
979
980         m_shaderSpec.outputs.push_back(Symbol("result", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
981         m_shaderSpec.outputs.push_back(Symbol("sampledCoord", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
982         m_shaderSpec.inputs .push_back(Symbol("coord", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
983         m_shaderSpec.inputs .push_back(Symbol("layer", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
984         m_shaderSpec.inputs .push_back(Symbol("dRef", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
985         m_shaderSpec.inputs .push_back(Symbol("dPdx", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
986         m_shaderSpec.inputs .push_back(Symbol("dPdy", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
987         m_shaderSpec.inputs .push_back(Symbol("lod", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
988
989         m_shaderSpec.globalDeclarations = "layout(set=" + de::toString((int)EXTRA_RESOURCES_DESCRIPTOR_SET_INDEX) + ", binding=0) uniform highp ";
990         m_shaderSpec.globalDeclarations += genSamplerDeclaration(m_testCaseData.imParams,
991                                                                                                                    m_testCaseData.samplerParams);
992         m_shaderSpec.globalDeclarations += " testSampler;";
993 }
994
995 class Texture2DGradientTestCase : public TextureFilteringTestCase
996 {
997 public:
998         Texture2DGradientTestCase (TestContext&                 testCtx,
999                                                            const char*                  name,
1000                                                            const char*                  desc,
1001                                                            TextureFormat                format,
1002                                                            IVec3                                dimensions,
1003                                                            VkFilter                             magFilter,
1004                                                            VkFilter                             minFilter,
1005                                                            VkSamplerMipmapMode  mipmapFilter,
1006                                                            VkSamplerAddressMode wrappingMode,
1007                                                            bool                                 useDerivatives)
1008
1009                 : TextureFilteringTestCase      (testCtx, name, desc)
1010                 , m_format                                      (format)
1011                 , m_dimensions                          (dimensions)
1012                 , m_magFilter                           (magFilter)
1013                 , m_minFilter                           (minFilter)
1014                 , m_mipmapFilter                        (mipmapFilter)
1015                 , m_wrappingMode                        (wrappingMode)
1016                 , m_useDerivatives                      (useDerivatives)
1017         {
1018                 m_testCaseData = genTestCaseData();
1019                 initSpec();
1020         }
1021
1022 protected:
1023         class Generator;
1024
1025         virtual de::MovePtr<DataGenerator> createGenerator (void) const;
1026
1027         TestCaseData genTestCaseData()
1028         {
1029                 // Generate grid
1030
1031                 const SampleLookupSettings sampleLookupSettings =
1032                 {
1033                         m_useDerivatives ? LOOKUP_LOD_MODE_DERIVATIVES : LOOKUP_LOD_MODE_LOD, // lookupLodMode
1034                         false, // hasLodBias
1035                         false, // isProjective
1036                 };
1037
1038                 const SamplerParameters samplerParameters =
1039                 {
1040                         m_magFilter,
1041                         m_minFilter,
1042                         m_mipmapFilter,
1043                         m_wrappingMode,
1044                         m_wrappingMode,
1045                         m_wrappingMode,
1046                         VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,
1047                         0.0f,
1048                         -1.0f,
1049                         50.0f,
1050                         false,
1051                         false
1052                 };
1053
1054                 const deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_dimensions[0],
1055                                                                                                                                            m_dimensions[1])));
1056
1057                 const ImageViewParameters imParameters =
1058                 {
1059                         IMG_DIM_2D,
1060                         mapTextureFormat(m_format),
1061                         m_dimensions,
1062                         numLevels,
1063                         false,
1064                         1,
1065                 };
1066
1067                 const TestCaseData data =
1068                 {
1069                         std::vector<ConstPixelBufferAccess>(),
1070                         imParameters,
1071                         samplerParameters,
1072                         sampleLookupSettings,
1073                         glu::SHADERTYPE_FRAGMENT
1074                 };
1075
1076                 return data;
1077         }
1078
1079 private:
1080         const TextureFormat                     m_format;
1081         const IVec3                                     m_dimensions;
1082         const VkFilter                          m_magFilter;
1083         const VkFilter                          m_minFilter;
1084         const VkSamplerMipmapMode       m_mipmapFilter;
1085         const VkSamplerAddressMode      m_wrappingMode;
1086         const bool                                      m_useDerivatives;
1087 };
1088
1089 class Texture2DGradientTestCase::Generator : public DataGenerator
1090 {
1091 public:
1092         Generator (const Texture2DGradientTestCase* testCase) : m_testCase(testCase) {}
1093
1094         virtual ~Generator (void)
1095         {
1096                 delete m_tex.release();
1097         }
1098
1099         virtual bool generate (void)
1100         {
1101                 m_tex = de::MovePtr<Texture2D>(new Texture2D(m_testCase->m_format,
1102                                                                                                          m_testCase->m_dimensions[0],
1103                                                                                                          m_testCase->m_dimensions[1]));
1104
1105                 const deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_testCase->m_dimensions[0],
1106                                                                                                                                            m_testCase->m_dimensions[1])));
1107
1108                 const TextureFormatInfo fmtInfo = getTextureFormatInfo(m_testCase->m_format);
1109
1110                 const Vec4 cBias  = fmtInfo.valueMin;
1111                 const Vec4 cScale = fmtInfo.valueMax - fmtInfo.valueMin;
1112
1113                 for (deUint8 levelNdx = 0; levelNdx < numLevels; ++levelNdx)
1114                 {
1115                         const Vec4 gMin = Vec4(0.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
1116                         const Vec4 gMax = Vec4(1.0f, 1.0f, 1.0f, 0.0f) * cScale + cBias;
1117
1118                         m_tex->allocLevel(levelNdx);
1119                         fillWithComponentGradients(m_tex->getLevel(levelNdx), gMin, gMax);
1120                 }
1121
1122                 return true;
1123         }
1124
1125         virtual std::vector<ConstPixelBufferAccess> getPba (void) const
1126         {
1127                 std::vector<ConstPixelBufferAccess> pba;
1128
1129                 const deUint8 numLevels = (deUint8) m_tex->getNumLevels();
1130
1131                 for (deUint8 levelNdx = 0; levelNdx < numLevels; ++levelNdx)
1132                 {
1133                         pba.push_back(m_tex->getLevel(levelNdx));
1134                 }
1135
1136                 return pba;
1137         }
1138
1139         virtual std::vector<SampleArguments> getSampleArgs (void) const
1140         {
1141                 std::vector<SampleArguments> args;
1142
1143                 if (m_testCase->m_useDerivatives)
1144                 {
1145                         struct
1146                         {
1147                                 Vec4 dPdx;
1148                                 Vec4 dPdy;
1149                         }
1150                         derivativePairs[] =
1151                         {
1152                                 {Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(0.0f, 0.0f, 0.0f, 0.0f)},
1153                                 {Vec4(1.0f, 1.0f, 1.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f)},
1154                                 {Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f)},
1155                                 {Vec4(1.0f, 1.0f, 1.0f, 0.0f), Vec4(0.0f, 0.0f, 0.0f, 0.0f)},
1156                                 {Vec4(2.0f, 2.0f, 2.0f, 0.0f), Vec4(2.0f, 2.0f, 2.0f, 0.0f)}
1157                         };
1158
1159                         for (deInt32 i = 0; i < 2 * m_testCase->m_dimensions[0] + 1; ++i)
1160                         {
1161                                 for (deInt32 j = 0; j < 2 * m_testCase->m_dimensions[1] + 1; ++j)
1162                                 {
1163                                     for (deUint32 derivNdx = 0; derivNdx < DE_LENGTH_OF_ARRAY(derivativePairs); ++derivNdx)
1164                                         {
1165                                                 SampleArguments cur = SampleArguments();
1166                                                 cur.coord = Vec4((float)i / (float)(2 * m_testCase->m_dimensions[0]),
1167                                                                                  (float)j / (float)(2 * m_testCase->m_dimensions[1]),
1168                                                                                  0.0f, 0.0f);
1169                                                 cur.dPdx = derivativePairs[derivNdx].dPdx;
1170                                                 cur.dPdy = derivativePairs[derivNdx].dPdy;
1171
1172                                                 args.push_back(cur);
1173                                         }
1174                                 }
1175                         }
1176                 }
1177                 else
1178                 {
1179                         const float lodList[] = {-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0};
1180
1181                         for (deInt32 i = 0; i < 2 * m_testCase->m_dimensions[0] + 1; ++i)
1182                         {
1183                                 for (deInt32 j = 0; j < 2 * m_testCase->m_dimensions[1] + 1; ++j)
1184                                 {
1185                                         for (deUint32 lodNdx = 0; lodNdx < DE_LENGTH_OF_ARRAY(lodList); ++lodNdx)
1186                                         {
1187                                                 SampleArguments cur = SampleArguments();
1188                                                 cur.coord = Vec4((float)i / (float)(2 * m_testCase->m_dimensions[0]),
1189                                                                                  (float)j / (float)(2 * m_testCase->m_dimensions[1]),
1190                                                                                  0.0f, 0.0f);
1191                                                 cur.lod = lodList[lodNdx];
1192
1193                                                 args.push_back(cur);
1194                                         }
1195                                 }
1196                         }
1197                 }
1198
1199                 return args;
1200         }
1201
1202 private:
1203         const Texture2DGradientTestCase*        m_testCase;
1204         de::MovePtr<Texture2D>                          m_tex;
1205 };
1206
1207 de::MovePtr<DataGenerator> Texture2DGradientTestCase::createGenerator (void) const
1208 {
1209         return de::MovePtr<DataGenerator>(new Generator(this));
1210 }
1211
1212 TestCaseGroup* create2DFormatTests (TestContext& testCtx)
1213 {
1214         de::MovePtr<TestCaseGroup> tests(
1215                 new TestCaseGroup(testCtx, "formats", "Various image formats"));
1216
1217     const VkFormat formats[] =
1218         {
1219             VK_FORMAT_B4G4R4A4_UNORM_PACK16,
1220                 VK_FORMAT_R5G6B5_UNORM_PACK16,
1221                 VK_FORMAT_A1R5G5B5_UNORM_PACK16,
1222                 VK_FORMAT_R8_UNORM,
1223                 VK_FORMAT_R8_SNORM,
1224                 VK_FORMAT_R8G8_UNORM,
1225                 VK_FORMAT_R8G8_SNORM,
1226                 VK_FORMAT_R8G8B8A8_UNORM,
1227                 VK_FORMAT_R8G8B8A8_SNORM,
1228 //              VK_FORMAT_R8G8B8A8_SRGB,
1229                 VK_FORMAT_B8G8R8A8_UNORM,
1230 //              VK_FORMAT_B8G8R8A8_SRGB,
1231                 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1232                 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
1233 //              VK_FORMAT_A8B8G8R8_SRGB_PACK32,
1234                 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1235                 VK_FORMAT_R16_SFLOAT,
1236                 VK_FORMAT_R16G16_SFLOAT,
1237                 VK_FORMAT_R16G16B16A16_SFLOAT,
1238                 VK_FORMAT_R32_SFLOAT,
1239                 VK_FORMAT_R32G32_SFLOAT,
1240                 VK_FORMAT_R32G32B32A32_SFLOAT,
1241 //              VK_FORMAT_B10G11R11_UFLOAT_PACK32,
1242 //              VK_FORMAT_E5B9G9R9_UFLOAT_PACK32
1243         };
1244
1245         const IVec3 size(32, 32, 1);
1246
1247         for (deUint32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
1248         {
1249                 const std::string prefix = de::toLower(std::string(getFormatName(formats[formatNdx])).substr(10));
1250
1251                 Texture2DGradientTestCase* testCaseNearest =
1252                         new Texture2DGradientTestCase(
1253                                 testCtx,
1254                             (prefix + "_nearest").c_str(),
1255                                 "...",
1256                                 mapVkFormat(formats[formatNdx]),
1257                                 size,
1258                                 VK_FILTER_NEAREST,
1259                                 VK_FILTER_NEAREST,
1260                                 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1261                                 VK_SAMPLER_ADDRESS_MODE_REPEAT,
1262                                 false);
1263
1264                 tests->addChild(testCaseNearest);
1265
1266             Texture2DGradientTestCase* testCaseLinear =
1267                         new Texture2DGradientTestCase(
1268                                 testCtx,
1269                             (prefix + "_linear").c_str(),
1270                                 "...",
1271                                 mapVkFormat(formats[formatNdx]),
1272                                 size,
1273                                 VK_FILTER_LINEAR,
1274                                 VK_FILTER_LINEAR,
1275                                 VK_SAMPLER_MIPMAP_MODE_LINEAR,
1276                                 VK_SAMPLER_ADDRESS_MODE_REPEAT,
1277                                 false);
1278
1279                 tests->addChild(testCaseLinear);
1280         }
1281
1282         return tests.release();
1283 }
1284
1285 TestCaseGroup* create2DDerivTests (TestContext& testCtx)
1286 {
1287         de::MovePtr<TestCaseGroup> tests(
1288                 new TestCaseGroup(testCtx, "derivatives", "Explicit derivative tests"));
1289
1290         const VkFormat                          format           = VK_FORMAT_R8G8B8A8_UNORM;
1291         const VkSamplerAddressMode      wrappingMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1292         const IVec3                                     size             = IVec3(16, 16, 1);
1293
1294         const VkFilter filters[2] =
1295         {
1296                 VK_FILTER_NEAREST,
1297                 VK_FILTER_LINEAR
1298         };
1299
1300         const VkSamplerMipmapMode mipmapFilters[2] =
1301         {
1302                 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1303                 VK_SAMPLER_MIPMAP_MODE_LINEAR,
1304         };
1305
1306         for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(filters); ++magFilterNdx)
1307         {
1308                 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(filters); ++minFilterNdx)
1309                 {
1310                         for (int mipmapFilterNdx = 0; mipmapFilterNdx < DE_LENGTH_OF_ARRAY(mipmapFilters); ++mipmapFilterNdx)
1311                         {
1312                                 std::ostringstream caseName;
1313
1314                                 switch (filters[magFilterNdx])
1315                                 {
1316                                         case VK_FILTER_NEAREST:
1317                                                 caseName << "nearest";
1318                                                 break;
1319
1320                                         case VK_FILTER_LINEAR:
1321                                                 caseName << "linear";
1322                                                 break;
1323
1324                                         default:
1325                                                 break;
1326                                 }
1327
1328                                 switch (filters[minFilterNdx])
1329                                 {
1330                                         case VK_FILTER_NEAREST:
1331                                                 caseName << "_nearest";
1332                                                 break;
1333
1334                                         case VK_FILTER_LINEAR:
1335                                                 caseName << "_linear";
1336                                                 break;
1337
1338                                         default:
1339                                                 break;
1340                                 }
1341
1342                                 caseName << "_mipmap";
1343
1344                                 switch (mipmapFilters[mipmapFilterNdx])
1345                                 {
1346                                         case VK_SAMPLER_MIPMAP_MODE_NEAREST:
1347                                                 caseName << "_nearest";
1348                                                 break;
1349
1350                                         case VK_SAMPLER_MIPMAP_MODE_LINEAR:
1351                                                 caseName << "_linear";
1352                                                 break;
1353
1354                                         default:
1355                                                 break;
1356                                 }
1357
1358                                 Texture2DGradientTestCase* testCase =
1359                                         new Texture2DGradientTestCase(
1360                                                 testCtx,
1361                                                 caseName.str().c_str(),
1362                                                 "...",
1363                                                 mapVkFormat(format),
1364                                                 size,
1365                                                 filters[magFilterNdx],
1366                                                 filters[minFilterNdx],
1367                                                 mipmapFilters[mipmapFilterNdx],
1368                                                 wrappingMode,
1369                                                 true);
1370
1371                                 tests->addChild(testCase);
1372                         }
1373                 }
1374         }
1375
1376         return tests.release();
1377 }
1378
1379 TestCaseGroup* create2DSizeTests (TestContext& testCtx)
1380 {
1381         de::MovePtr<TestCaseGroup> tests(
1382                 new TestCaseGroup(testCtx, "sizes", "Various size and filtering combinations"));
1383
1384         const VkFilter filters[2] =
1385         {
1386                 VK_FILTER_NEAREST,
1387                 VK_FILTER_LINEAR
1388         };
1389
1390         const VkSamplerMipmapMode mipmapFilters[2] =
1391         {
1392                 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1393                 VK_SAMPLER_MIPMAP_MODE_LINEAR
1394         };
1395
1396         const VkSamplerAddressMode wrappingModes[2] =
1397         {
1398                 VK_SAMPLER_ADDRESS_MODE_REPEAT,
1399                 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE
1400         };
1401
1402         const IVec3 sizes[] =
1403         {
1404                 IVec3(2, 2, 1),
1405                 IVec3(2, 3, 1),
1406                 IVec3(3, 7, 1),
1407                 IVec3(4, 8, 1),
1408                 IVec3(31, 55, 1),
1409                 IVec3(32, 32, 1),
1410                 IVec3(32, 64, 1),
1411                 IVec3(57, 35, 1),
1412                 IVec3(128, 128, 1)
1413         };
1414
1415
1416         for (deUint32 sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1417         {
1418                 for (deUint32 magFilterNdx = 0; magFilterNdx < 2; ++magFilterNdx)
1419                 {
1420                         for (deUint32 minFilterNdx = 0; minFilterNdx < 2; ++minFilterNdx)
1421                         {
1422                                 for (deUint32 mipmapFilterNdx = 0; mipmapFilterNdx < 2; ++mipmapFilterNdx)
1423                                 {
1424                                         for (deUint32 wrappingModeNdx = 0; wrappingModeNdx < 2; ++wrappingModeNdx)
1425                                         {
1426                                                 std::ostringstream caseName;
1427
1428                                                 caseName << sizes[sizeNdx][0] << "x" << sizes[sizeNdx][1];
1429
1430                                                 switch (filters[magFilterNdx])
1431                                                 {
1432                                                         case VK_FILTER_NEAREST:
1433                                                                 caseName << "_nearest";
1434                                                                 break;
1435
1436                                                         case VK_FILTER_LINEAR:
1437                                                                 caseName << "_linear";
1438                                                                 break;
1439
1440                                                         default:
1441                                                                 break;
1442                                                 }
1443
1444                                                 switch (filters[minFilterNdx])
1445                                                 {
1446                                                         case VK_FILTER_NEAREST:
1447                                                                 caseName << "_nearest";
1448                                                                 break;
1449
1450                                                         case VK_FILTER_LINEAR:
1451                                                                 caseName << "_linear";
1452                                                                 break;
1453
1454                                                         default:
1455                                                                 break;
1456                                                 }
1457
1458                                                 switch (mipmapFilters[mipmapFilterNdx])
1459                                                 {
1460                                                         case VK_SAMPLER_MIPMAP_MODE_NEAREST:
1461                                                                 caseName << "_mipmap_nearest";
1462                                                                 break;
1463
1464                                                         case VK_SAMPLER_MIPMAP_MODE_LINEAR:
1465                                                                 caseName << "_mipmap_linear";
1466                                                                 break;
1467
1468                                                         default:
1469                                                                 break;
1470                                                 }
1471
1472                                                 switch (wrappingModes[wrappingModeNdx])
1473                                                 {
1474                                                         case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
1475                                                                 caseName << "_clamp";
1476                                                                 break;
1477
1478                                                         case VK_SAMPLER_ADDRESS_MODE_REPEAT:
1479                                                                 caseName << "_repeat";
1480                                                                 break;
1481
1482                                                         default:
1483                                                                 break;
1484                                                 }
1485
1486                                                 Texture2DGradientTestCase* testCase =
1487                                                         new Texture2DGradientTestCase(
1488                                                                 testCtx,
1489                                                                 caseName.str().c_str(),
1490                                                                 "...",
1491                                                                 mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM),
1492                                                                 sizes[sizeNdx],
1493                                                                 filters[magFilterNdx],
1494                                                                 filters[minFilterNdx],
1495                                                                 mipmapFilters[mipmapFilterNdx],
1496                                                                 wrappingModes[wrappingModeNdx],
1497                                                                 false);
1498
1499                                                 tests->addChild(testCase);
1500                                         }
1501                                 }
1502                         }
1503                 }
1504         }
1505
1506         return tests.release();
1507 }
1508
1509 TestCaseGroup* create2DTests (TestContext& testCtx)
1510 {
1511         de::MovePtr<TestCaseGroup> tests(
1512                 new TestCaseGroup(testCtx, "2d", "2D Image filtering tests"));
1513
1514         tests->addChild(create2DSizeTests(testCtx));
1515         tests->addChild(create2DFormatTests(testCtx));
1516         tests->addChild(create2DDerivTests(testCtx));
1517
1518         return tests.release();
1519 }
1520
1521 } // anonymous
1522
1523 TestCaseGroup* createExplicitLodTests (TestContext& testCtx)
1524 {
1525         de::MovePtr<TestCaseGroup> tests(
1526                 new TestCaseGroup(testCtx, "explicit_lod", "Texture filtering with explicit LOD"));
1527
1528         tests->addChild(create2DTests(testCtx));
1529
1530         return tests.release();
1531 }
1532
1533 } // texture
1534 } // vkt