1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2016 Google Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief Texture filtering tests with explicit LOD instructions
22 *//*--------------------------------------------------------------------*/
24 #include "vktTextureFilteringExplicitLodTests.hpp"
28 #include "vktSampleVerifier.hpp"
29 #include "vktShaderExecutor.hpp"
30 #include "vktTestCaseUtil.hpp"
32 #include "vkDeviceUtil.hpp"
33 #include "vkImageUtil.hpp"
34 #include "vkPlatform.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkStrUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkQueryUtil.hpp"
40 #include "vkMemUtil.hpp"
41 #include "vkCmdUtil.hpp"
43 #include "tcuTexLookupVerifier.hpp"
44 #include "tcuTestLog.hpp"
45 #include "tcuTexture.hpp"
46 #include "tcuTextureUtil.hpp"
47 #include "tcuVector.hpp"
51 #include "deStringUtil.hpp"
52 #include "deUniquePtr.hpp"
70 std::vector<tcu::FloatFormat> getPrecision (VkFormat format)
72 std::vector<tcu::FloatFormat> floatFormats;
73 const tcu::FloatFormat fp16 (-14, 15, 10, false);
74 const tcu::FloatFormat fp32 (-126, 127, 23, true);
75 const tcu::TextureFormat tcuFormat = mapVkFormat(format);
76 const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(tcuFormat.type);
77 const tcu::IVec4 channelDepth = tcu::getTextureFormatBitDepth(tcuFormat);
79 for (int channelIdx = 0; channelIdx < 4; channelIdx++)
83 case TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
84 case TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
85 floatFormats.push_back(tcu::FloatFormat(0, 0, channelDepth[channelIdx], false, tcu::YES));
88 case TEXTURECHANNELCLASS_FLOATING_POINT:
89 if (channelDepth[channelIdx] == 16)
91 floatFormats.push_back(fp16);
95 DE_ASSERT(channelDepth[channelIdx] == 32 || channelDepth[channelIdx] == 0);
96 floatFormats.push_back(fp32);
101 DE_FATAL("Unexpected channel class.");
109 using namespace shaderexecutor;
111 string genSamplerDeclaration(const ImageViewParameters& imParams,
112 const SamplerParameters& samplerParams)
114 string result = "sampler";
116 switch (imParams.dim)
138 if (imParams.isArrayed)
143 if (samplerParams.isCompare)
151 string genLookupCode(const ImageViewParameters& imParams,
152 const SamplerParameters& samplerParams,
153 const SampleLookupSettings& lookupSettings)
157 switch (imParams.dim)
180 DE_ASSERT(dim >= 1 && dim <= 3);
182 int numCoordComp = dim;
184 if (lookupSettings.isProjective)
189 int numArgComp = numCoordComp;
190 bool hasSeparateCompare = false;
192 if (imParams.isArrayed)
194 DE_ASSERT(!lookupSettings.isProjective && "Can't do a projective lookup on an arrayed image!");
199 if (samplerParams.isCompare && numCoordComp == 4)
201 hasSeparateCompare = true;
203 else if (samplerParams.isCompare)
208 // Build coordinate input to texture*() function
211 arg += (char) (numArgComp + '0');
213 arg += (char) (numCoordComp + '0');
216 int numZero = numArgComp - numCoordComp;
218 if (imParams.isArrayed)
224 if (samplerParams.isCompare && !hasSeparateCompare)
230 for (int ndx = 0; ndx < numZero; ++ndx)
237 // Build call to texture*() function
241 code += "result = texture";
243 if (lookupSettings.isProjective)
248 if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
252 else if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_LOD)
257 code += "(testSampler, ";
260 if (samplerParams.isCompare && hasSeparateCompare)
265 if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
268 code += (char) (numCoordComp + '0');
271 code += (char) (numCoordComp + '0');
274 else if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_LOD)
284 void initializeImage(Context& ctx, VkImage im, const ConstPixelBufferAccess* pba, ImageViewParameters imParams)
286 const DeviceInterface& vkd = ctx.getDeviceInterface();
287 const VkDevice dev = ctx.getDevice();
288 const deUint32 uqfi = ctx.getUniversalQueueFamilyIndex();
290 const VkDeviceSize bufSize =
291 getPixelSize(mapVkFormat(imParams.format))
292 * imParams.arrayLayers
298 const VkBufferCreateInfo bufCreateInfo =
300 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
304 VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage
305 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
306 1, // queueFamilyIndexCount
307 &uqfi // pQueueFamilyIndices
310 Unique<VkBuffer> buf(createBuffer(vkd, dev, &bufCreateInfo));
312 VkMemoryRequirements bufMemReq;
313 vkd.getBufferMemoryRequirements(dev, buf.get(), &bufMemReq);
315 de::UniquePtr<Allocation> bufMem(ctx.getDefaultAllocator().allocate(bufMemReq, MemoryRequirement::HostVisible));
316 VK_CHECK(vkd.bindBufferMemory(dev, buf.get(), bufMem->getMemory(), bufMem->getOffset()));
318 std::vector<VkBufferImageCopy> copyRegions;
320 deUint8* const bufMapPtr = reinterpret_cast<deUint8*>(bufMem->getHostPtr());
321 deUint8* bufCurPtr = bufMapPtr;
323 for (int level = 0; level < imParams.levels; ++level)
325 const IVec3 curLevelSize = pba[level].getSize();
327 const std::size_t copySize =
328 getPixelSize(mapVkFormat(imParams.format))
329 * curLevelSize[0] * curLevelSize[1] * curLevelSize[2]
330 * imParams.arrayLayers;
332 deMemcpy(bufCurPtr, pba[level].getDataPtr(), copySize);
334 const VkImageSubresourceLayers curSubresource =
336 VK_IMAGE_ASPECT_COLOR_BIT,
339 (deUint32)imParams.arrayLayers
342 const VkBufferImageCopy curRegion =
344 (VkDeviceSize) (bufCurPtr - bufMapPtr),
349 {(deUint32)curLevelSize[0], (deUint32)curLevelSize[1], (deUint32)curLevelSize[2]}
352 copyRegions.push_back(curRegion);
354 bufCurPtr += copySize;
357 flushAlloc(vkd, dev, *bufMem);
359 copyBufferToImage(vkd, dev, ctx.getUniversalQueue(), ctx.getUniversalQueueFamilyIndex(), buf.get(), bufSize, copyRegions, DE_NULL, VK_IMAGE_ASPECT_COLOR_BIT, imParams.levels, imParams.arrayLayers, im);
364 std::vector<ConstPixelBufferAccess> pba;
365 ImageViewParameters imParams;
366 SamplerParameters samplerParams;
367 SampleLookupSettings sampleLookupSettings;
368 glu::ShaderType shaderType;
371 VkSamplerCreateInfo mapSamplerCreateInfo (const SamplerParameters& samplerParams)
373 VkSamplerCreateInfo samplerCreateInfo =
375 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // sType
378 samplerParams.magFilter, // magFilter
379 samplerParams.minFilter, // minFilter
380 samplerParams.mipmapFilter, // mipmapMode
381 samplerParams.wrappingModeU, // addressModeU
382 samplerParams.wrappingModeV, // addressModeV
383 samplerParams.wrappingModeW, // addressMoveW
384 samplerParams.lodBias, // mipLodBias
385 VK_FALSE, // anisotropyEnable
386 1.0f, // maxAnisotropy
387 VK_FALSE, // compareEnable
388 VK_COMPARE_OP_NEVER, // compareOp
389 samplerParams.minLod, // minLod
390 samplerParams.maxLod, // maxLod
391 samplerParams.borderColor, // borderColor
392 samplerParams.isUnnormalized ? VK_TRUE : VK_FALSE, // unnormalizedCoordinates
395 if (samplerParams.isCompare)
397 samplerCreateInfo.compareEnable = VK_TRUE;
399 DE_FATAL("Not implemented");
402 return samplerCreateInfo;
405 VkImageType mapImageType (ImgDim dim)
412 imType = VK_IMAGE_TYPE_1D;
417 imType = VK_IMAGE_TYPE_2D;
421 imType = VK_IMAGE_TYPE_3D;
425 imType = VK_IMAGE_TYPE_LAST;
432 VkImageViewType mapImageViewType (const ImageViewParameters& imParams)
434 VkImageViewType imViewType;
436 if (imParams.isArrayed)
438 switch (imParams.dim)
441 imViewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
445 imViewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
449 imViewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
453 imViewType = VK_IMAGE_VIEW_TYPE_LAST;
459 switch (imParams.dim)
462 imViewType = VK_IMAGE_VIEW_TYPE_1D;
466 imViewType = VK_IMAGE_VIEW_TYPE_2D;
470 imViewType = VK_IMAGE_VIEW_TYPE_3D;
474 imViewType = VK_IMAGE_VIEW_TYPE_CUBE;
478 imViewType = VK_IMAGE_VIEW_TYPE_LAST;
489 virtual ~DataGenerator (void) {}
491 virtual bool generate (void) = 0;
493 virtual std::vector<ConstPixelBufferAccess> getPba (void) const = 0;
494 virtual std::vector<SampleArguments> getSampleArgs (void) const = 0;
497 DataGenerator (void) {}
500 class TextureFilteringTestInstance : public TestInstance
503 TextureFilteringTestInstance (Context& ctx,
504 const TestCaseData& testCaseData,
505 const ShaderSpec& shaderSpec,
506 de::MovePtr<DataGenerator> gen);
508 virtual TestStatus iterate (void) { return runTest(); }
511 TestStatus runTest (void);
512 bool isSupported (void);
513 void createResources (void);
517 tcu::Sampler mapTcuSampler (void) const;
519 const glu::ShaderType m_shaderType;
520 const ShaderSpec m_shaderSpec;
521 const ImageViewParameters m_imParams;
522 const SamplerParameters m_samplerParams;
523 const SampleLookupSettings m_sampleLookupSettings;
525 std::vector<SampleArguments> m_sampleArguments;
526 deUint32 m_numSamples;
528 de::MovePtr<Allocation> m_imAllocation;
530 Move<VkImageView> m_imView;
531 Move<VkSampler> m_sampler;
533 Move<VkDescriptorSetLayout> m_extraResourcesLayout;
534 Move<VkDescriptorPool> m_extraResourcesPool;
535 Move<VkDescriptorSet> m_extraResourcesSet;
537 de::MovePtr<ShaderExecutor> m_executor;
539 std::vector<ConstPixelBufferAccess> m_levels;
540 de::MovePtr<DataGenerator> m_gen;
542 std::vector<Vec4> m_resultSamples;
543 std::vector<Vec4> m_resultCoords;
546 TextureFilteringTestInstance::TextureFilteringTestInstance (Context& ctx,
547 const TestCaseData& testCaseData,
548 const ShaderSpec& shaderSpec,
549 de::MovePtr<DataGenerator> gen)
551 , m_shaderType (testCaseData.shaderType)
552 , m_shaderSpec (shaderSpec)
553 , m_imParams (testCaseData.imParams)
554 , m_samplerParams (testCaseData.samplerParams)
555 , m_sampleLookupSettings (testCaseData.sampleLookupSettings)
556 , m_levels (testCaseData.pba)
557 , m_gen (gen.release())
559 for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
560 DE_ASSERT(m_imParams.size[compNdx] > 0);
563 TestStatus TextureFilteringTestInstance::runTest (void)
566 TCU_THROW(NotSupportedError, "Unsupported combination of filtering and image format");
568 TCU_CHECK(m_gen->generate());
569 m_levels = m_gen->getPba();
571 m_sampleArguments = m_gen->getSampleArgs();
572 m_numSamples = (deUint32)m_sampleArguments.size();
575 initializeImage(m_context, m_im.get(), &m_levels[0], m_imParams);
577 deUint64 startTime, endTime;
579 startTime = deGetMicroseconds();
581 endTime = deGetMicroseconds();
583 m_context.getTestContext().getLog() << TestLog::Message
584 << "Execution time: "
585 << endTime - startTime
587 << TestLog::EndMessage;
589 startTime = deGetMicroseconds();
590 bool result = verify();
591 endTime = deGetMicroseconds();
593 m_context.getTestContext().getLog() << TestLog::Message
594 << "Verification time: "
595 << endTime - startTime
597 << TestLog::EndMessage;
601 return TestStatus::pass("Success");
605 // \todo [2016-06-24 collinbaker] Print report if verification fails
606 return TestStatus::fail("Verification failed");
610 bool TextureFilteringTestInstance::verify (void)
612 // \todo [2016-06-24 collinbaker] Handle cubemaps
614 const int coordBits = (int)m_context.getDeviceProperties().limits.subTexelPrecisionBits;
615 const int mipmapBits = (int)m_context.getDeviceProperties().limits.mipmapPrecisionBits;
616 const int maxPrintedFailures = 5;
619 const SampleVerifier verifier (m_imParams,
621 m_sampleLookupSettings,
624 getPrecision(m_imParams.format),
625 getPrecision(m_imParams.format),
629 for (deUint32 sampleNdx = 0; sampleNdx < m_numSamples; ++sampleNdx)
631 if (!verifier.verifySample(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx]))
633 if (failCount++ < maxPrintedFailures)
635 // Re-run with report logging
637 verifier.verifySampleReport(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx], report);
639 m_context.getTestContext().getLog()
640 << TestLog::Section("Failed sample", "Failed sample")
642 << "Sample " << sampleNdx << ".\n"
643 << "\tCoordinate: " << m_sampleArguments[sampleNdx].coord << "\n"
644 << "\tLOD: " << m_sampleArguments[sampleNdx].lod << "\n"
645 << "\tGPU Result: " << m_resultSamples[sampleNdx] << "\n\n"
646 << "Failure report:\n" << report << "\n"
647 << TestLog::EndMessage
648 << TestLog::EndSection;
653 m_context.getTestContext().getLog()
655 << "Passed " << m_numSamples - failCount << " out of " << m_numSamples << "."
656 << TestLog::EndMessage;
658 return failCount == 0;
661 void TextureFilteringTestInstance::execute (void)
663 std::vector<float> coords, layers, dRefs, dPdxs, dPdys, lods;
665 for (deUint32 ndx = 0; ndx < m_numSamples; ++ndx)
667 const SampleArguments& sampleArgs = m_sampleArguments[ndx];
669 for (deUint8 compNdx = 0; compNdx < 4; ++compNdx)
671 coords.push_back(sampleArgs.coord[compNdx]);
672 dPdxs .push_back(sampleArgs.dPdx[compNdx]);
673 dPdys .push_back(sampleArgs.dPdy[compNdx]);
676 layers.push_back(sampleArgs.layer);
677 dRefs .push_back(sampleArgs.dRef);
678 lods .push_back(sampleArgs.lod);
681 const void* inputs[6] =
683 reinterpret_cast<const void*>(&coords[0]),
684 reinterpret_cast<const void*>(&layers[0]),
685 reinterpret_cast<const void*>(&dRefs[0]),
686 reinterpret_cast<const void*>(&dPdxs[0]),
687 reinterpret_cast<const void*>(&dPdys[0]),
688 reinterpret_cast<const void*>(&lods[0])
691 // Staging buffers; data will be copied into vectors of Vec4
692 // \todo [2016-06-24 collinbaker] Figure out if I actually need to
693 // use staging buffers
694 std::vector<float> resultSamplesTemp(m_numSamples * 4);
695 std::vector<float> resultCoordsTemp (m_numSamples * 4);
699 reinterpret_cast<void*>(&resultSamplesTemp[0]),
700 reinterpret_cast<void*>(&resultCoordsTemp[0])
703 m_executor->execute(m_numSamples, inputs, outputs, *m_extraResourcesSet);
705 m_resultSamples.resize(m_numSamples);
706 m_resultCoords .resize(m_numSamples);
708 for (deUint32 ndx = 0; ndx < m_numSamples; ++ndx)
710 m_resultSamples[ndx] = Vec4(resultSamplesTemp[4 * ndx + 0],
711 resultSamplesTemp[4 * ndx + 1],
712 resultSamplesTemp[4 * ndx + 2],
713 resultSamplesTemp[4 * ndx + 3]);
715 m_resultCoords [ndx] = Vec4(resultCoordsTemp [4 * ndx + 0],
716 resultCoordsTemp [4 * ndx + 1],
717 resultCoordsTemp [4 * ndx + 2],
718 resultCoordsTemp [4 * ndx + 3]);
722 void TextureFilteringTestInstance::createResources (void)
726 const DeviceInterface& vkd = m_context.getDeviceInterface();
727 const VkDevice device = m_context.getDevice();
729 const deUint32 queueFamily = m_context.getUniversalQueueFamilyIndex();
730 const VkImageCreateFlags imCreateFlags =(m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
732 const VkImageCreateInfo imCreateInfo =
734 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
737 mapImageType(m_imParams.dim),
739 makeExtent3D(m_imParams.size[0], m_imParams.size[1], m_imParams.size[2]),
740 (deUint32)m_imParams.levels,
741 (deUint32)m_imParams.arrayLayers,
742 VK_SAMPLE_COUNT_1_BIT,
743 VK_IMAGE_TILING_OPTIMAL,
744 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
745 VK_SHARING_MODE_EXCLUSIVE,
748 VK_IMAGE_LAYOUT_UNDEFINED
751 m_im = createImage(vkd, device, &imCreateInfo);
753 // Allocate memory for image
755 VkMemoryRequirements imMemReq;
756 vkd.getImageMemoryRequirements(device, m_im.get(), &imMemReq);
758 m_imAllocation = m_context.getDefaultAllocator().allocate(imMemReq, MemoryRequirement::Any);
759 VK_CHECK(vkd.bindImageMemory(device, m_im.get(), m_imAllocation->getMemory(), m_imAllocation->getOffset()));
761 // Create VkImageView
763 // \todo [2016-06-23 collinbaker] Pick aspectMask based on image type (i.e. support depth and/or stencil images)
764 DE_ASSERT(m_imParams.dim != IMG_DIM_CUBE); // \todo Support cube maps
765 const VkImageSubresourceRange imViewSubresourceRange =
767 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
769 (deUint32)m_imParams.levels, // levelCount
771 (deUint32)m_imParams.arrayLayers // layerCount
774 const VkComponentMapping imViewCompMap =
776 VK_COMPONENT_SWIZZLE_R,
777 VK_COMPONENT_SWIZZLE_G,
778 VK_COMPONENT_SWIZZLE_B,
779 VK_COMPONENT_SWIZZLE_A
782 const VkImageViewCreateInfo imViewCreateInfo =
784 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType
788 mapImageViewType(m_imParams), // viewType
789 m_imParams.format, // format
790 imViewCompMap, // components
791 imViewSubresourceRange // subresourceRange
794 m_imView = createImageView(vkd, device, &imViewCreateInfo);
798 const VkSamplerCreateInfo samplerCreateInfo = mapSamplerCreateInfo(m_samplerParams);
799 m_sampler = createSampler(vkd, device, &samplerCreateInfo);
801 // Create additional descriptors
804 const VkDescriptorSetLayoutBinding bindings[] =
806 { 0u, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u, VK_SHADER_STAGE_ALL, DE_NULL },
808 const VkDescriptorSetLayoutCreateInfo layoutInfo =
810 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
812 (VkDescriptorSetLayoutCreateFlags)0u,
813 DE_LENGTH_OF_ARRAY(bindings),
817 m_extraResourcesLayout = createDescriptorSetLayout(vkd, device, &layoutInfo);
821 const VkDescriptorPoolSize poolSizes[] =
823 { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u },
825 const VkDescriptorPoolCreateInfo poolInfo =
827 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
829 (VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
831 DE_LENGTH_OF_ARRAY(poolSizes),
835 m_extraResourcesPool = createDescriptorPool(vkd, device, &poolInfo);
839 const VkDescriptorSetAllocateInfo allocInfo =
841 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
843 *m_extraResourcesPool,
845 &m_extraResourcesLayout.get(),
848 m_extraResourcesSet = allocateDescriptorSet(vkd, device, &allocInfo);
852 const VkDescriptorImageInfo imageInfo =
856 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
858 const VkWriteDescriptorSet descriptorWrite =
860 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
862 *m_extraResourcesSet,
864 0u, // dstArrayElement
866 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
868 (const VkDescriptorBufferInfo*)DE_NULL,
869 (const VkBufferView*)DE_NULL,
872 vkd.updateDescriptorSets(device, 1u, &descriptorWrite, 0u, DE_NULL);
875 m_executor = de::MovePtr<ShaderExecutor>(createExecutor(m_context, m_shaderType, m_shaderSpec, *m_extraResourcesLayout));
878 VkFormatFeatureFlags getRequiredFormatFeatures (const SamplerParameters& samplerParams)
880 VkFormatFeatureFlags features = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
882 if (samplerParams.minFilter == VK_FILTER_LINEAR ||
883 samplerParams.magFilter == VK_FILTER_LINEAR ||
884 samplerParams.mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
886 features |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
892 bool TextureFilteringTestInstance::isSupported (void)
894 const VkImageCreateFlags imCreateFlags = (m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
895 const VkFormatFeatureFlags reqImFeatures = getRequiredFormatFeatures(m_samplerParams);
897 const VkImageFormatProperties imFormatProperties = getPhysicalDeviceImageFormatProperties(m_context.getInstanceInterface(),
898 m_context.getPhysicalDevice(),
900 mapImageType(m_imParams.dim),
901 VK_IMAGE_TILING_OPTIMAL,
902 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
904 const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(m_context.getInstanceInterface(),
905 m_context.getPhysicalDevice(),
908 // \todo [2016-06-23 collinbaker] Check image parameters against imFormatProperties
909 DE_UNREF(imFormatProperties);
911 return (formatProperties.optimalTilingFeatures & reqImFeatures) == reqImFeatures;
914 class TextureFilteringTestCase : public TestCase
917 TextureFilteringTestCase (tcu::TestContext& testCtx,
919 const char* description)
920 : TestCase(testCtx, name, description)
924 void initSpec (void);
926 virtual void initPrograms (vk::SourceCollections& programCollection) const
928 generateSources(m_testCaseData.shaderType, m_shaderSpec, programCollection);
931 virtual de::MovePtr<DataGenerator> createGenerator (void) const = 0;
933 virtual TestInstance* createInstance (Context& ctx) const
935 return new TextureFilteringTestInstance(ctx, m_testCaseData, m_shaderSpec, createGenerator());
939 de::MovePtr<ShaderExecutor> m_executor;
940 TestCaseData m_testCaseData;
941 ShaderSpec m_shaderSpec;
944 void TextureFilteringTestCase::initSpec (void)
946 m_shaderSpec.source = genLookupCode(m_testCaseData.imParams,
947 m_testCaseData.samplerParams,
948 m_testCaseData.sampleLookupSettings);
949 m_shaderSpec.source += "\nsampledCoord = coord;";
951 m_shaderSpec.outputs.push_back(Symbol("result", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
952 m_shaderSpec.outputs.push_back(Symbol("sampledCoord", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
953 m_shaderSpec.inputs .push_back(Symbol("coord", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
954 m_shaderSpec.inputs .push_back(Symbol("layer", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
955 m_shaderSpec.inputs .push_back(Symbol("dRef", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
956 m_shaderSpec.inputs .push_back(Symbol("dPdx", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
957 m_shaderSpec.inputs .push_back(Symbol("dPdy", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
958 m_shaderSpec.inputs .push_back(Symbol("lod", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
960 m_shaderSpec.globalDeclarations = "layout(set=" + de::toString((int)EXTRA_RESOURCES_DESCRIPTOR_SET_INDEX) + ", binding=0) uniform highp ";
961 m_shaderSpec.globalDeclarations += genSamplerDeclaration(m_testCaseData.imParams,
962 m_testCaseData.samplerParams);
963 m_shaderSpec.globalDeclarations += " testSampler;";
966 class Texture2DGradientTestCase : public TextureFilteringTestCase
969 Texture2DGradientTestCase (TestContext& testCtx,
972 TextureFormat format,
976 VkSamplerMipmapMode mipmapFilter,
977 VkSamplerAddressMode wrappingMode,
980 : TextureFilteringTestCase (testCtx, name, desc)
982 , m_dimensions (dimensions)
983 , m_magFilter (magFilter)
984 , m_minFilter (minFilter)
985 , m_mipmapFilter (mipmapFilter)
986 , m_wrappingMode (wrappingMode)
987 , m_useDerivatives (useDerivatives)
989 m_testCaseData = genTestCaseData();
996 virtual de::MovePtr<DataGenerator> createGenerator (void) const;
998 TestCaseData genTestCaseData()
1002 const SampleLookupSettings sampleLookupSettings =
1004 m_useDerivatives ? LOOKUP_LOD_MODE_DERIVATIVES : LOOKUP_LOD_MODE_LOD, // lookupLodMode
1005 false, // hasLodBias
1006 false, // isProjective
1009 const SamplerParameters samplerParameters =
1017 VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,
1025 const deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_dimensions[0],
1028 const ImageViewParameters imParameters =
1031 mapTextureFormat(m_format),
1038 const TestCaseData data =
1040 std::vector<ConstPixelBufferAccess>(),
1043 sampleLookupSettings,
1044 glu::SHADERTYPE_FRAGMENT
1051 const TextureFormat m_format;
1052 const IVec3 m_dimensions;
1053 const VkFilter m_magFilter;
1054 const VkFilter m_minFilter;
1055 const VkSamplerMipmapMode m_mipmapFilter;
1056 const VkSamplerAddressMode m_wrappingMode;
1057 const bool m_useDerivatives;
1060 class Texture2DGradientTestCase::Generator : public DataGenerator
1063 Generator (const Texture2DGradientTestCase* testCase) : m_testCase(testCase) {}
1065 virtual ~Generator (void)
1067 delete m_tex.release();
1070 virtual bool generate (void)
1072 m_tex = de::MovePtr<Texture2D>(new Texture2D(m_testCase->m_format,
1073 m_testCase->m_dimensions[0],
1074 m_testCase->m_dimensions[1]));
1076 const deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_testCase->m_dimensions[0],
1077 m_testCase->m_dimensions[1])));
1079 const TextureFormatInfo fmtInfo = getTextureFormatInfo(m_testCase->m_format);
1081 const Vec4 cBias = fmtInfo.valueMin;
1082 const Vec4 cScale = fmtInfo.valueMax - fmtInfo.valueMin;
1084 for (deUint8 levelNdx = 0; levelNdx < numLevels; ++levelNdx)
1086 const Vec4 gMin = Vec4(0.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
1087 const Vec4 gMax = Vec4(1.0f, 1.0f, 1.0f, 0.0f) * cScale + cBias;
1089 m_tex->allocLevel(levelNdx);
1090 fillWithComponentGradients(m_tex->getLevel(levelNdx), gMin, gMax);
1096 virtual std::vector<ConstPixelBufferAccess> getPba (void) const
1098 std::vector<ConstPixelBufferAccess> pba;
1100 const deUint8 numLevels = (deUint8) m_tex->getNumLevels();
1102 for (deUint8 levelNdx = 0; levelNdx < numLevels; ++levelNdx)
1104 pba.push_back(m_tex->getLevel(levelNdx));
1110 virtual std::vector<SampleArguments> getSampleArgs (void) const
1112 std::vector<SampleArguments> args;
1114 if (m_testCase->m_useDerivatives)
1123 {Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(0.0f, 0.0f, 0.0f, 0.0f)},
1124 {Vec4(1.0f, 1.0f, 1.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f)},
1125 {Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f)},
1126 {Vec4(1.0f, 1.0f, 1.0f, 0.0f), Vec4(0.0f, 0.0f, 0.0f, 0.0f)},
1127 {Vec4(2.0f, 2.0f, 2.0f, 0.0f), Vec4(2.0f, 2.0f, 2.0f, 0.0f)}
1130 for (deInt32 i = 0; i < 2 * m_testCase->m_dimensions[0] + 1; ++i)
1132 for (deInt32 j = 0; j < 2 * m_testCase->m_dimensions[1] + 1; ++j)
1134 for (deUint32 derivNdx = 0; derivNdx < DE_LENGTH_OF_ARRAY(derivativePairs); ++derivNdx)
1136 SampleArguments cur = SampleArguments();
1137 cur.coord = Vec4((float)i / (float)(2 * m_testCase->m_dimensions[0]),
1138 (float)j / (float)(2 * m_testCase->m_dimensions[1]),
1140 cur.dPdx = derivativePairs[derivNdx].dPdx;
1141 cur.dPdy = derivativePairs[derivNdx].dPdy;
1143 args.push_back(cur);
1150 const float lodList[] = {-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0};
1152 for (deInt32 i = 0; i < 2 * m_testCase->m_dimensions[0] + 1; ++i)
1154 for (deInt32 j = 0; j < 2 * m_testCase->m_dimensions[1] + 1; ++j)
1156 for (deUint32 lodNdx = 0; lodNdx < DE_LENGTH_OF_ARRAY(lodList); ++lodNdx)
1158 SampleArguments cur = SampleArguments();
1159 cur.coord = Vec4((float)i / (float)(2 * m_testCase->m_dimensions[0]),
1160 (float)j / (float)(2 * m_testCase->m_dimensions[1]),
1162 cur.lod = lodList[lodNdx];
1164 args.push_back(cur);
1174 const Texture2DGradientTestCase* m_testCase;
1175 de::MovePtr<Texture2D> m_tex;
1178 de::MovePtr<DataGenerator> Texture2DGradientTestCase::createGenerator (void) const
1180 return de::MovePtr<DataGenerator>(new Generator(this));
1183 TestCaseGroup* create2DFormatTests (TestContext& testCtx)
1185 de::MovePtr<TestCaseGroup> tests(
1186 new TestCaseGroup(testCtx, "formats", "Various image formats"));
1188 const VkFormat formats[] =
1190 VK_FORMAT_B4G4R4A4_UNORM_PACK16,
1191 VK_FORMAT_R5G6B5_UNORM_PACK16,
1192 VK_FORMAT_A1R5G5B5_UNORM_PACK16,
1195 VK_FORMAT_R8G8_UNORM,
1196 VK_FORMAT_R8G8_SNORM,
1197 VK_FORMAT_R8G8B8A8_UNORM,
1198 VK_FORMAT_R8G8B8A8_SNORM,
1199 // VK_FORMAT_R8G8B8A8_SRGB,
1200 VK_FORMAT_B8G8R8A8_UNORM,
1201 // VK_FORMAT_B8G8R8A8_SRGB,
1202 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1203 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
1204 // VK_FORMAT_A8B8G8R8_SRGB_PACK32,
1205 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1206 VK_FORMAT_R16_SFLOAT,
1207 VK_FORMAT_R16G16_SFLOAT,
1208 VK_FORMAT_R16G16B16A16_SFLOAT,
1209 VK_FORMAT_R32_SFLOAT,
1210 VK_FORMAT_R32G32_SFLOAT,
1211 VK_FORMAT_R32G32B32A32_SFLOAT,
1212 // VK_FORMAT_B10G11R11_UFLOAT_PACK32,
1213 // VK_FORMAT_E5B9G9R9_UFLOAT_PACK32
1216 const IVec3 size(32, 32, 1);
1218 for (deUint32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
1220 const std::string prefix = de::toLower(std::string(getFormatName(formats[formatNdx])).substr(10));
1222 Texture2DGradientTestCase* testCaseNearest =
1223 new Texture2DGradientTestCase(
1225 (prefix + "_nearest").c_str(),
1227 mapVkFormat(formats[formatNdx]),
1231 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1232 VK_SAMPLER_ADDRESS_MODE_REPEAT,
1235 tests->addChild(testCaseNearest);
1237 Texture2DGradientTestCase* testCaseLinear =
1238 new Texture2DGradientTestCase(
1240 (prefix + "_linear").c_str(),
1242 mapVkFormat(formats[formatNdx]),
1246 VK_SAMPLER_MIPMAP_MODE_LINEAR,
1247 VK_SAMPLER_ADDRESS_MODE_REPEAT,
1250 tests->addChild(testCaseLinear);
1253 return tests.release();
1256 TestCaseGroup* create2DDerivTests (TestContext& testCtx)
1258 de::MovePtr<TestCaseGroup> tests(
1259 new TestCaseGroup(testCtx, "derivatives", "Explicit derivative tests"));
1261 const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1262 const VkSamplerAddressMode wrappingMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1263 const IVec3 size = IVec3(16, 16, 1);
1265 const VkFilter filters[2] =
1271 const VkSamplerMipmapMode mipmapFilters[2] =
1273 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1274 VK_SAMPLER_MIPMAP_MODE_LINEAR,
1277 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(filters); ++magFilterNdx)
1279 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(filters); ++minFilterNdx)
1281 for (int mipmapFilterNdx = 0; mipmapFilterNdx < DE_LENGTH_OF_ARRAY(mipmapFilters); ++mipmapFilterNdx)
1283 std::ostringstream caseName;
1285 switch (filters[magFilterNdx])
1287 case VK_FILTER_NEAREST:
1288 caseName << "nearest";
1291 case VK_FILTER_LINEAR:
1292 caseName << "linear";
1299 switch (filters[minFilterNdx])
1301 case VK_FILTER_NEAREST:
1302 caseName << "_nearest";
1305 case VK_FILTER_LINEAR:
1306 caseName << "_linear";
1313 caseName << "_mipmap";
1315 switch (mipmapFilters[mipmapFilterNdx])
1317 case VK_SAMPLER_MIPMAP_MODE_NEAREST:
1318 caseName << "_nearest";
1321 case VK_SAMPLER_MIPMAP_MODE_LINEAR:
1322 caseName << "_linear";
1329 Texture2DGradientTestCase* testCase =
1330 new Texture2DGradientTestCase(
1332 caseName.str().c_str(),
1334 mapVkFormat(format),
1336 filters[magFilterNdx],
1337 filters[minFilterNdx],
1338 mipmapFilters[mipmapFilterNdx],
1342 tests->addChild(testCase);
1347 return tests.release();
1350 TestCaseGroup* create2DSizeTests (TestContext& testCtx)
1352 de::MovePtr<TestCaseGroup> tests(
1353 new TestCaseGroup(testCtx, "sizes", "Various size and filtering combinations"));
1355 const VkFilter filters[2] =
1361 const VkSamplerMipmapMode mipmapFilters[2] =
1363 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1364 VK_SAMPLER_MIPMAP_MODE_LINEAR
1367 const VkSamplerAddressMode wrappingModes[2] =
1369 VK_SAMPLER_ADDRESS_MODE_REPEAT,
1370 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE
1373 const IVec3 sizes[] =
1387 for (deUint32 sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1389 for (deUint32 magFilterNdx = 0; magFilterNdx < 2; ++magFilterNdx)
1391 for (deUint32 minFilterNdx = 0; minFilterNdx < 2; ++minFilterNdx)
1393 for (deUint32 mipmapFilterNdx = 0; mipmapFilterNdx < 2; ++mipmapFilterNdx)
1395 for (deUint32 wrappingModeNdx = 0; wrappingModeNdx < 2; ++wrappingModeNdx)
1397 std::ostringstream caseName;
1399 caseName << sizes[sizeNdx][0] << "x" << sizes[sizeNdx][1];
1401 switch (filters[magFilterNdx])
1403 case VK_FILTER_NEAREST:
1404 caseName << "_nearest";
1407 case VK_FILTER_LINEAR:
1408 caseName << "_linear";
1415 switch (filters[minFilterNdx])
1417 case VK_FILTER_NEAREST:
1418 caseName << "_nearest";
1421 case VK_FILTER_LINEAR:
1422 caseName << "_linear";
1429 switch (mipmapFilters[mipmapFilterNdx])
1431 case VK_SAMPLER_MIPMAP_MODE_NEAREST:
1432 caseName << "_mipmap_nearest";
1435 case VK_SAMPLER_MIPMAP_MODE_LINEAR:
1436 caseName << "_mipmap_linear";
1443 switch (wrappingModes[wrappingModeNdx])
1445 case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
1446 caseName << "_clamp";
1449 case VK_SAMPLER_ADDRESS_MODE_REPEAT:
1450 caseName << "_repeat";
1457 Texture2DGradientTestCase* testCase =
1458 new Texture2DGradientTestCase(
1460 caseName.str().c_str(),
1462 mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM),
1464 filters[magFilterNdx],
1465 filters[minFilterNdx],
1466 mipmapFilters[mipmapFilterNdx],
1467 wrappingModes[wrappingModeNdx],
1470 tests->addChild(testCase);
1477 return tests.release();
1480 TestCaseGroup* create2DTests (TestContext& testCtx)
1482 de::MovePtr<TestCaseGroup> tests(
1483 new TestCaseGroup(testCtx, "2d", "2D Image filtering tests"));
1485 tests->addChild(create2DSizeTests(testCtx));
1486 tests->addChild(create2DFormatTests(testCtx));
1487 tests->addChild(create2DDerivTests(testCtx));
1489 return tests.release();
1494 TestCaseGroup* createExplicitLodTests (TestContext& testCtx)
1496 de::MovePtr<TestCaseGroup> tests(
1497 new TestCaseGroup(testCtx, "explicit_lod", "Texture filtering with explicit LOD"));
1499 tests->addChild(create2DTests(testCtx));
1501 return tests.release();