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