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