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, int fpPrecisionDelta)
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, std::max(0,channelDepth[channelIdx] + fpPrecisionDelta), false, tcu::YES));
88 case TEXTURECHANNELCLASS_FLOATING_POINT:
89 if (channelDepth[channelIdx] == 16)
91 floatFormats.push_back(tcu::FloatFormat(fp16.getMinExp(), fp16.getMaxExp(), std::max(0,fp16.getFractionBits() + fpPrecisionDelta), false, tcu::YES));
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;
618 const tcu::TextureFormat tcuFormat = mapVkFormat(m_imParams.format);
619 std::vector<tcu::FloatFormat> strictPrecision = getPrecision(m_imParams.format, 0);
620 std::vector<tcu::FloatFormat> relaxedPrecision = tcuFormat.type == tcu::TextureFormat::HALF_FLOAT ? getPrecision(m_imParams.format, -3) : getPrecision(m_imParams.format, -2);
621 const bool allowRelaxedPrecision = (tcuFormat.type == tcu::TextureFormat::HALF_FLOAT || tcuFormat.type == tcu::TextureFormat::SNORM_INT8) &&
622 (m_samplerParams.minFilter == VK_FILTER_LINEAR || m_samplerParams.magFilter == VK_FILTER_LINEAR);
624 const SampleVerifier verifier (m_imParams,
626 m_sampleLookupSettings,
633 const SampleVerifier relaxedVerifier (m_imParams,
635 m_sampleLookupSettings,
642 for (deUint32 sampleNdx = 0; sampleNdx < m_numSamples; ++sampleNdx)
644 bool compareOK = verifier.verifySample(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx]);
647 if (allowRelaxedPrecision)
649 m_context.getTestContext().getLog()
650 << tcu::TestLog::Message
651 << "Warning: Strict validation failed, re-trying with lower precision for SNORM8 format or half float"
652 << tcu::TestLog::EndMessage;
654 compareOK = relaxedVerifier.verifySample(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx]);
658 if ( failCount++ < maxPrintedFailures )
660 // Re-run with report logging
662 verifier.verifySampleReport(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx], report);
664 m_context.getTestContext().getLog()
665 << TestLog::Section("Failed sample", "Failed sample")
667 << "Sample " << sampleNdx << ".\n"
668 << "\tCoordinate: " << m_sampleArguments[sampleNdx].coord << "\n"
669 << "\tLOD: " << m_sampleArguments[sampleNdx].lod << "\n"
670 << "\tGPU Result: " << m_resultSamples[sampleNdx] << "\n\n"
671 << "Failure report:\n" << report << "\n"
672 << TestLog::EndMessage
673 << TestLog::EndSection;
677 m_context.getTestContext().getLog()
679 << "Passed " << m_numSamples - failCount << " out of " << m_numSamples << "."
680 << TestLog::EndMessage;
682 return failCount == 0;
685 void TextureFilteringTestInstance::execute (void)
687 std::vector<float> coords, layers, dRefs, dPdxs, dPdys, lods;
689 for (deUint32 ndx = 0; ndx < m_numSamples; ++ndx)
691 const SampleArguments& sampleArgs = m_sampleArguments[ndx];
693 for (deUint8 compNdx = 0; compNdx < 4; ++compNdx)
695 coords.push_back(sampleArgs.coord[compNdx]);
696 dPdxs .push_back(sampleArgs.dPdx[compNdx]);
697 dPdys .push_back(sampleArgs.dPdy[compNdx]);
700 layers.push_back(sampleArgs.layer);
701 dRefs .push_back(sampleArgs.dRef);
702 lods .push_back(sampleArgs.lod);
705 const void* inputs[6] =
707 reinterpret_cast<const void*>(&coords[0]),
708 reinterpret_cast<const void*>(&layers[0]),
709 reinterpret_cast<const void*>(&dRefs[0]),
710 reinterpret_cast<const void*>(&dPdxs[0]),
711 reinterpret_cast<const void*>(&dPdys[0]),
712 reinterpret_cast<const void*>(&lods[0])
715 // Staging buffers; data will be copied into vectors of Vec4
716 // \todo [2016-06-24 collinbaker] Figure out if I actually need to
717 // use staging buffers
718 std::vector<float> resultSamplesTemp(m_numSamples * 4);
719 std::vector<float> resultCoordsTemp (m_numSamples * 4);
723 reinterpret_cast<void*>(&resultSamplesTemp[0]),
724 reinterpret_cast<void*>(&resultCoordsTemp[0])
727 m_executor->execute(m_numSamples, inputs, outputs, *m_extraResourcesSet);
729 m_resultSamples.resize(m_numSamples);
730 m_resultCoords .resize(m_numSamples);
732 for (deUint32 ndx = 0; ndx < m_numSamples; ++ndx)
734 m_resultSamples[ndx] = Vec4(resultSamplesTemp[4 * ndx + 0],
735 resultSamplesTemp[4 * ndx + 1],
736 resultSamplesTemp[4 * ndx + 2],
737 resultSamplesTemp[4 * ndx + 3]);
739 m_resultCoords [ndx] = Vec4(resultCoordsTemp [4 * ndx + 0],
740 resultCoordsTemp [4 * ndx + 1],
741 resultCoordsTemp [4 * ndx + 2],
742 resultCoordsTemp [4 * ndx + 3]);
746 void TextureFilteringTestInstance::createResources (void)
750 const DeviceInterface& vkd = m_context.getDeviceInterface();
751 const VkDevice device = m_context.getDevice();
753 const deUint32 queueFamily = m_context.getUniversalQueueFamilyIndex();
754 const VkImageCreateFlags imCreateFlags =(m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
756 const VkImageCreateInfo imCreateInfo =
758 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
761 mapImageType(m_imParams.dim),
763 makeExtent3D(m_imParams.size[0], m_imParams.size[1], m_imParams.size[2]),
764 (deUint32)m_imParams.levels,
765 (deUint32)m_imParams.arrayLayers,
766 VK_SAMPLE_COUNT_1_BIT,
767 VK_IMAGE_TILING_OPTIMAL,
768 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
769 VK_SHARING_MODE_EXCLUSIVE,
772 VK_IMAGE_LAYOUT_UNDEFINED
775 m_im = createImage(vkd, device, &imCreateInfo);
777 // Allocate memory for image
779 VkMemoryRequirements imMemReq;
780 vkd.getImageMemoryRequirements(device, m_im.get(), &imMemReq);
782 m_imAllocation = m_context.getDefaultAllocator().allocate(imMemReq, MemoryRequirement::Any);
783 VK_CHECK(vkd.bindImageMemory(device, m_im.get(), m_imAllocation->getMemory(), m_imAllocation->getOffset()));
785 // Create VkImageView
787 // \todo [2016-06-23 collinbaker] Pick aspectMask based on image type (i.e. support depth and/or stencil images)
788 DE_ASSERT(m_imParams.dim != IMG_DIM_CUBE); // \todo Support cube maps
789 const VkImageSubresourceRange imViewSubresourceRange =
791 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
793 (deUint32)m_imParams.levels, // levelCount
795 (deUint32)m_imParams.arrayLayers // layerCount
798 const VkComponentMapping imViewCompMap =
800 VK_COMPONENT_SWIZZLE_R,
801 VK_COMPONENT_SWIZZLE_G,
802 VK_COMPONENT_SWIZZLE_B,
803 VK_COMPONENT_SWIZZLE_A
806 const VkImageViewCreateInfo imViewCreateInfo =
808 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType
812 mapImageViewType(m_imParams), // viewType
813 m_imParams.format, // format
814 imViewCompMap, // components
815 imViewSubresourceRange // subresourceRange
818 m_imView = createImageView(vkd, device, &imViewCreateInfo);
822 const VkSamplerCreateInfo samplerCreateInfo = mapSamplerCreateInfo(m_samplerParams);
823 m_sampler = createSampler(vkd, device, &samplerCreateInfo);
825 // Create additional descriptors
828 const VkDescriptorSetLayoutBinding bindings[] =
830 { 0u, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u, VK_SHADER_STAGE_ALL, DE_NULL },
832 const VkDescriptorSetLayoutCreateInfo layoutInfo =
834 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
836 (VkDescriptorSetLayoutCreateFlags)0u,
837 DE_LENGTH_OF_ARRAY(bindings),
841 m_extraResourcesLayout = createDescriptorSetLayout(vkd, device, &layoutInfo);
845 const VkDescriptorPoolSize poolSizes[] =
847 { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u },
849 const VkDescriptorPoolCreateInfo poolInfo =
851 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
853 (VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
855 DE_LENGTH_OF_ARRAY(poolSizes),
859 m_extraResourcesPool = createDescriptorPool(vkd, device, &poolInfo);
863 const VkDescriptorSetAllocateInfo allocInfo =
865 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
867 *m_extraResourcesPool,
869 &m_extraResourcesLayout.get(),
872 m_extraResourcesSet = allocateDescriptorSet(vkd, device, &allocInfo);
876 const VkDescriptorImageInfo imageInfo =
880 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
882 const VkWriteDescriptorSet descriptorWrite =
884 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
886 *m_extraResourcesSet,
888 0u, // dstArrayElement
890 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
892 (const VkDescriptorBufferInfo*)DE_NULL,
893 (const VkBufferView*)DE_NULL,
896 vkd.updateDescriptorSets(device, 1u, &descriptorWrite, 0u, DE_NULL);
899 m_executor = de::MovePtr<ShaderExecutor>(createExecutor(m_context, m_shaderType, m_shaderSpec, *m_extraResourcesLayout));
902 VkFormatFeatureFlags getRequiredFormatFeatures (const SamplerParameters& samplerParams)
904 VkFormatFeatureFlags features = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
906 if (samplerParams.minFilter == VK_FILTER_LINEAR ||
907 samplerParams.magFilter == VK_FILTER_LINEAR ||
908 samplerParams.mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
910 features |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
916 bool TextureFilteringTestInstance::isSupported (void)
918 const VkImageCreateFlags imCreateFlags = (m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
919 const VkFormatFeatureFlags reqImFeatures = getRequiredFormatFeatures(m_samplerParams);
921 const VkImageFormatProperties imFormatProperties = getPhysicalDeviceImageFormatProperties(m_context.getInstanceInterface(),
922 m_context.getPhysicalDevice(),
924 mapImageType(m_imParams.dim),
925 VK_IMAGE_TILING_OPTIMAL,
926 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
928 const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(m_context.getInstanceInterface(),
929 m_context.getPhysicalDevice(),
932 // \todo [2016-06-23 collinbaker] Check image parameters against imFormatProperties
933 DE_UNREF(imFormatProperties);
935 return (formatProperties.optimalTilingFeatures & reqImFeatures) == reqImFeatures;
938 class TextureFilteringTestCase : public TestCase
941 TextureFilteringTestCase (tcu::TestContext& testCtx,
943 const char* description)
944 : TestCase(testCtx, name, description)
948 void initSpec (void);
950 virtual void initPrograms (vk::SourceCollections& programCollection) const
952 generateSources(m_testCaseData.shaderType, m_shaderSpec, programCollection);
955 virtual de::MovePtr<DataGenerator> createGenerator (void) const = 0;
957 virtual TestInstance* createInstance (Context& ctx) const
959 return new TextureFilteringTestInstance(ctx, m_testCaseData, m_shaderSpec, createGenerator());
963 de::MovePtr<ShaderExecutor> m_executor;
964 TestCaseData m_testCaseData;
965 ShaderSpec m_shaderSpec;
968 void TextureFilteringTestCase::initSpec (void)
970 m_shaderSpec.source = genLookupCode(m_testCaseData.imParams,
971 m_testCaseData.samplerParams,
972 m_testCaseData.sampleLookupSettings);
973 m_shaderSpec.source += "\nsampledCoord = coord;";
975 m_shaderSpec.outputs.push_back(Symbol("result", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
976 m_shaderSpec.outputs.push_back(Symbol("sampledCoord", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
977 m_shaderSpec.inputs .push_back(Symbol("coord", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
978 m_shaderSpec.inputs .push_back(Symbol("layer", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
979 m_shaderSpec.inputs .push_back(Symbol("dRef", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
980 m_shaderSpec.inputs .push_back(Symbol("dPdx", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
981 m_shaderSpec.inputs .push_back(Symbol("dPdy", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
982 m_shaderSpec.inputs .push_back(Symbol("lod", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
984 m_shaderSpec.globalDeclarations = "layout(set=" + de::toString((int)EXTRA_RESOURCES_DESCRIPTOR_SET_INDEX) + ", binding=0) uniform highp ";
985 m_shaderSpec.globalDeclarations += genSamplerDeclaration(m_testCaseData.imParams,
986 m_testCaseData.samplerParams);
987 m_shaderSpec.globalDeclarations += " testSampler;";
990 class Texture2DGradientTestCase : public TextureFilteringTestCase
993 Texture2DGradientTestCase (TestContext& testCtx,
996 TextureFormat format,
1000 VkSamplerMipmapMode mipmapFilter,
1001 VkSamplerAddressMode wrappingMode,
1002 bool useDerivatives)
1004 : TextureFilteringTestCase (testCtx, name, desc)
1006 , m_dimensions (dimensions)
1007 , m_magFilter (magFilter)
1008 , m_minFilter (minFilter)
1009 , m_mipmapFilter (mipmapFilter)
1010 , m_wrappingMode (wrappingMode)
1011 , m_useDerivatives (useDerivatives)
1013 m_testCaseData = genTestCaseData();
1020 virtual de::MovePtr<DataGenerator> createGenerator (void) const;
1022 TestCaseData genTestCaseData()
1026 const SampleLookupSettings sampleLookupSettings =
1028 m_useDerivatives ? LOOKUP_LOD_MODE_DERIVATIVES : LOOKUP_LOD_MODE_LOD, // lookupLodMode
1029 false, // hasLodBias
1030 false, // isProjective
1033 const SamplerParameters samplerParameters =
1041 VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,
1049 const deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_dimensions[0],
1052 const ImageViewParameters imParameters =
1055 mapTextureFormat(m_format),
1062 const TestCaseData data =
1064 std::vector<ConstPixelBufferAccess>(),
1067 sampleLookupSettings,
1068 glu::SHADERTYPE_FRAGMENT
1075 const TextureFormat m_format;
1076 const IVec3 m_dimensions;
1077 const VkFilter m_magFilter;
1078 const VkFilter m_minFilter;
1079 const VkSamplerMipmapMode m_mipmapFilter;
1080 const VkSamplerAddressMode m_wrappingMode;
1081 const bool m_useDerivatives;
1084 class Texture2DGradientTestCase::Generator : public DataGenerator
1087 Generator (const Texture2DGradientTestCase* testCase) : m_testCase(testCase) {}
1089 virtual ~Generator (void)
1091 delete m_tex.release();
1094 virtual bool generate (void)
1096 m_tex = de::MovePtr<Texture2D>(new Texture2D(m_testCase->m_format,
1097 m_testCase->m_dimensions[0],
1098 m_testCase->m_dimensions[1]));
1100 const deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_testCase->m_dimensions[0],
1101 m_testCase->m_dimensions[1])));
1103 const TextureFormatInfo fmtInfo = getTextureFormatInfo(m_testCase->m_format);
1105 const Vec4 cBias = fmtInfo.valueMin;
1106 const Vec4 cScale = fmtInfo.valueMax - fmtInfo.valueMin;
1108 for (deUint8 levelNdx = 0; levelNdx < numLevels; ++levelNdx)
1110 const Vec4 gMin = Vec4(0.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
1111 const Vec4 gMax = Vec4(1.0f, 1.0f, 1.0f, 0.0f) * cScale + cBias;
1113 m_tex->allocLevel(levelNdx);
1114 fillWithComponentGradients(m_tex->getLevel(levelNdx), gMin, gMax);
1120 virtual std::vector<ConstPixelBufferAccess> getPba (void) const
1122 std::vector<ConstPixelBufferAccess> pba;
1124 const deUint8 numLevels = (deUint8) m_tex->getNumLevels();
1126 for (deUint8 levelNdx = 0; levelNdx < numLevels; ++levelNdx)
1128 pba.push_back(m_tex->getLevel(levelNdx));
1134 virtual std::vector<SampleArguments> getSampleArgs (void) const
1136 std::vector<SampleArguments> args;
1138 if (m_testCase->m_useDerivatives)
1147 {Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(0.0f, 0.0f, 0.0f, 0.0f)},
1148 {Vec4(1.0f, 1.0f, 1.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f)},
1149 {Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f)},
1150 {Vec4(1.0f, 1.0f, 1.0f, 0.0f), Vec4(0.0f, 0.0f, 0.0f, 0.0f)},
1151 {Vec4(2.0f, 2.0f, 2.0f, 0.0f), Vec4(2.0f, 2.0f, 2.0f, 0.0f)}
1154 for (deInt32 i = 0; i < 2 * m_testCase->m_dimensions[0] + 1; ++i)
1156 for (deInt32 j = 0; j < 2 * m_testCase->m_dimensions[1] + 1; ++j)
1158 for (deUint32 derivNdx = 0; derivNdx < DE_LENGTH_OF_ARRAY(derivativePairs); ++derivNdx)
1160 SampleArguments cur = SampleArguments();
1161 cur.coord = Vec4((float)i / (float)(2 * m_testCase->m_dimensions[0]),
1162 (float)j / (float)(2 * m_testCase->m_dimensions[1]),
1164 cur.dPdx = derivativePairs[derivNdx].dPdx;
1165 cur.dPdy = derivativePairs[derivNdx].dPdy;
1167 args.push_back(cur);
1174 const float lodList[] = {-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0};
1176 for (deInt32 i = 0; i < 2 * m_testCase->m_dimensions[0] + 1; ++i)
1178 for (deInt32 j = 0; j < 2 * m_testCase->m_dimensions[1] + 1; ++j)
1180 for (deUint32 lodNdx = 0; lodNdx < DE_LENGTH_OF_ARRAY(lodList); ++lodNdx)
1182 SampleArguments cur = SampleArguments();
1183 cur.coord = Vec4((float)i / (float)(2 * m_testCase->m_dimensions[0]),
1184 (float)j / (float)(2 * m_testCase->m_dimensions[1]),
1186 cur.lod = lodList[lodNdx];
1188 args.push_back(cur);
1198 const Texture2DGradientTestCase* m_testCase;
1199 de::MovePtr<Texture2D> m_tex;
1202 de::MovePtr<DataGenerator> Texture2DGradientTestCase::createGenerator (void) const
1204 return de::MovePtr<DataGenerator>(new Generator(this));
1207 TestCaseGroup* create2DFormatTests (TestContext& testCtx)
1209 de::MovePtr<TestCaseGroup> tests(
1210 new TestCaseGroup(testCtx, "formats", "Various image formats"));
1212 const VkFormat formats[] =
1214 VK_FORMAT_B4G4R4A4_UNORM_PACK16,
1215 VK_FORMAT_R5G6B5_UNORM_PACK16,
1216 VK_FORMAT_A1R5G5B5_UNORM_PACK16,
1219 VK_FORMAT_R8G8_UNORM,
1220 VK_FORMAT_R8G8_SNORM,
1221 VK_FORMAT_R8G8B8A8_UNORM,
1222 VK_FORMAT_R8G8B8A8_SNORM,
1223 // VK_FORMAT_R8G8B8A8_SRGB,
1224 VK_FORMAT_B8G8R8A8_UNORM,
1225 // VK_FORMAT_B8G8R8A8_SRGB,
1226 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1227 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
1228 // VK_FORMAT_A8B8G8R8_SRGB_PACK32,
1229 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1230 VK_FORMAT_R16_SFLOAT,
1231 VK_FORMAT_R16G16_SFLOAT,
1232 VK_FORMAT_R16G16B16A16_SFLOAT,
1233 VK_FORMAT_R32_SFLOAT,
1234 VK_FORMAT_R32G32_SFLOAT,
1235 VK_FORMAT_R32G32B32A32_SFLOAT,
1236 // VK_FORMAT_B10G11R11_UFLOAT_PACK32,
1237 // VK_FORMAT_E5B9G9R9_UFLOAT_PACK32
1240 const IVec3 size(32, 32, 1);
1242 for (deUint32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
1244 const std::string prefix = de::toLower(std::string(getFormatName(formats[formatNdx])).substr(10));
1246 Texture2DGradientTestCase* testCaseNearest =
1247 new Texture2DGradientTestCase(
1249 (prefix + "_nearest").c_str(),
1251 mapVkFormat(formats[formatNdx]),
1255 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1256 VK_SAMPLER_ADDRESS_MODE_REPEAT,
1259 tests->addChild(testCaseNearest);
1261 Texture2DGradientTestCase* testCaseLinear =
1262 new Texture2DGradientTestCase(
1264 (prefix + "_linear").c_str(),
1266 mapVkFormat(formats[formatNdx]),
1270 VK_SAMPLER_MIPMAP_MODE_LINEAR,
1271 VK_SAMPLER_ADDRESS_MODE_REPEAT,
1274 tests->addChild(testCaseLinear);
1277 return tests.release();
1280 TestCaseGroup* create2DDerivTests (TestContext& testCtx)
1282 de::MovePtr<TestCaseGroup> tests(
1283 new TestCaseGroup(testCtx, "derivatives", "Explicit derivative tests"));
1285 const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1286 const VkSamplerAddressMode wrappingMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1287 const IVec3 size = IVec3(16, 16, 1);
1289 const VkFilter filters[2] =
1295 const VkSamplerMipmapMode mipmapFilters[2] =
1297 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1298 VK_SAMPLER_MIPMAP_MODE_LINEAR,
1301 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(filters); ++magFilterNdx)
1303 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(filters); ++minFilterNdx)
1305 for (int mipmapFilterNdx = 0; mipmapFilterNdx < DE_LENGTH_OF_ARRAY(mipmapFilters); ++mipmapFilterNdx)
1307 std::ostringstream caseName;
1309 switch (filters[magFilterNdx])
1311 case VK_FILTER_NEAREST:
1312 caseName << "nearest";
1315 case VK_FILTER_LINEAR:
1316 caseName << "linear";
1323 switch (filters[minFilterNdx])
1325 case VK_FILTER_NEAREST:
1326 caseName << "_nearest";
1329 case VK_FILTER_LINEAR:
1330 caseName << "_linear";
1337 caseName << "_mipmap";
1339 switch (mipmapFilters[mipmapFilterNdx])
1341 case VK_SAMPLER_MIPMAP_MODE_NEAREST:
1342 caseName << "_nearest";
1345 case VK_SAMPLER_MIPMAP_MODE_LINEAR:
1346 caseName << "_linear";
1353 Texture2DGradientTestCase* testCase =
1354 new Texture2DGradientTestCase(
1356 caseName.str().c_str(),
1358 mapVkFormat(format),
1360 filters[magFilterNdx],
1361 filters[minFilterNdx],
1362 mipmapFilters[mipmapFilterNdx],
1366 tests->addChild(testCase);
1371 return tests.release();
1374 TestCaseGroup* create2DSizeTests (TestContext& testCtx)
1376 de::MovePtr<TestCaseGroup> tests(
1377 new TestCaseGroup(testCtx, "sizes", "Various size and filtering combinations"));
1379 const VkFilter filters[2] =
1385 const VkSamplerMipmapMode mipmapFilters[2] =
1387 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1388 VK_SAMPLER_MIPMAP_MODE_LINEAR
1391 const VkSamplerAddressMode wrappingModes[2] =
1393 VK_SAMPLER_ADDRESS_MODE_REPEAT,
1394 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE
1397 const IVec3 sizes[] =
1411 for (deUint32 sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1413 for (deUint32 magFilterNdx = 0; magFilterNdx < 2; ++magFilterNdx)
1415 for (deUint32 minFilterNdx = 0; minFilterNdx < 2; ++minFilterNdx)
1417 for (deUint32 mipmapFilterNdx = 0; mipmapFilterNdx < 2; ++mipmapFilterNdx)
1419 for (deUint32 wrappingModeNdx = 0; wrappingModeNdx < 2; ++wrappingModeNdx)
1421 std::ostringstream caseName;
1423 caseName << sizes[sizeNdx][0] << "x" << sizes[sizeNdx][1];
1425 switch (filters[magFilterNdx])
1427 case VK_FILTER_NEAREST:
1428 caseName << "_nearest";
1431 case VK_FILTER_LINEAR:
1432 caseName << "_linear";
1439 switch (filters[minFilterNdx])
1441 case VK_FILTER_NEAREST:
1442 caseName << "_nearest";
1445 case VK_FILTER_LINEAR:
1446 caseName << "_linear";
1453 switch (mipmapFilters[mipmapFilterNdx])
1455 case VK_SAMPLER_MIPMAP_MODE_NEAREST:
1456 caseName << "_mipmap_nearest";
1459 case VK_SAMPLER_MIPMAP_MODE_LINEAR:
1460 caseName << "_mipmap_linear";
1467 switch (wrappingModes[wrappingModeNdx])
1469 case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
1470 caseName << "_clamp";
1473 case VK_SAMPLER_ADDRESS_MODE_REPEAT:
1474 caseName << "_repeat";
1481 Texture2DGradientTestCase* testCase =
1482 new Texture2DGradientTestCase(
1484 caseName.str().c_str(),
1486 mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM),
1488 filters[magFilterNdx],
1489 filters[minFilterNdx],
1490 mipmapFilters[mipmapFilterNdx],
1491 wrappingModes[wrappingModeNdx],
1494 tests->addChild(testCase);
1501 return tests.release();
1504 TestCaseGroup* create2DTests (TestContext& testCtx)
1506 de::MovePtr<TestCaseGroup> tests(
1507 new TestCaseGroup(testCtx, "2d", "2D Image filtering tests"));
1509 tests->addChild(create2DSizeTests(testCtx));
1510 tests->addChild(create2DFormatTests(testCtx));
1511 tests->addChild(create2DDerivTests(testCtx));
1513 return tests.release();
1518 TestCaseGroup* createExplicitLodTests (TestContext& testCtx)
1520 de::MovePtr<TestCaseGroup> tests(
1521 new TestCaseGroup(testCtx, "explicit_lod", "Texture filtering with explicit LOD"));
1523 tests->addChild(create2DTests(testCtx));
1525 return tests.release();