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