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"
39 #include "tcuTexLookupVerifier.hpp"
40 #include "tcuTestLog.hpp"
41 #include "tcuTexture.hpp"
42 #include "tcuTextureUtil.hpp"
43 #include "tcuVector.hpp"
47 #include "deStringUtil.hpp"
48 #include "deUniquePtr.hpp"
56 namespace texture_filtering
66 using namespace shaderexecutor;
68 string genSamplerDeclaration(const ImageViewParameters& imParams,
69 const SamplerParameters& samplerParams)
71 string result = "sampler";
95 if (imParams.isArrayed)
100 if (samplerParams.isCompare)
108 string genLookupCode(const ImageViewParameters& imParams,
109 const SamplerParameters& samplerParams,
110 const SampleLookupSettings& lookupSettings)
114 switch (imParams.dim)
137 DE_ASSERT(dim >= 1 && dim <= 3);
139 int numCoordComp = dim;
141 if (lookupSettings.isProjective)
146 int numArgComp = numCoordComp;
147 bool hasSeparateCompare = false;
149 if (imParams.isArrayed)
151 DE_ASSERT(!lookupSettings.isProjective && "Can't do a projective lookup on an arrayed image!");
156 if (samplerParams.isCompare && numCoordComp == 4)
158 hasSeparateCompare = true;
160 else if (samplerParams.isCompare)
165 // Build coordinate input to texture*() function
168 arg += (char) (numArgComp + '0');
170 arg += (char) (numCoordComp + '0');
173 int numZero = numArgComp - numCoordComp;
175 if (imParams.isArrayed)
181 if (samplerParams.isCompare && !hasSeparateCompare)
187 for (int ndx = 0; ndx < numZero; ++ndx)
194 // Build call to texture*() function
198 code += "result = texture";
200 if (lookupSettings.isProjective)
205 if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
209 else if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_LOD)
214 code += "(testSampler, ";
217 if (samplerParams.isCompare && hasSeparateCompare)
222 if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
225 code += (char) (numCoordComp + '0');
228 code += (char) (numCoordComp + '0');
231 else if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_LOD)
241 void initializeImage(Context& ctx, VkImage im, const ConstPixelBufferAccess* pba, ImageViewParameters imParams)
243 const DeviceInterface& vkd = ctx.getDeviceInterface();
244 const VkDevice dev = ctx.getDevice();
245 const deUint32 uqfi = ctx.getUniversalQueueFamilyIndex();
247 const VkDeviceSize bufSize =
248 getPixelSize(mapVkFormat(imParams.format))
249 * imParams.arrayLayers
255 const VkBufferCreateInfo bufCreateInfo =
257 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
261 VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage
262 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
263 1, // queueFamilyIndexCount
264 &uqfi // pQueueFamilyIndices
267 Unique<VkBuffer> buf(createBuffer(vkd, dev, &bufCreateInfo));
269 VkMemoryRequirements bufMemReq;
270 vkd.getBufferMemoryRequirements(dev, buf.get(), &bufMemReq);
272 de::UniquePtr<Allocation> bufMem(ctx.getDefaultAllocator().allocate(bufMemReq, MemoryRequirement::HostVisible));
273 VK_CHECK(vkd.bindBufferMemory(dev, buf.get(), bufMem->getMemory(), bufMem->getOffset()));
275 const VkCommandPoolCreateInfo copyPoolCreateInfo =
277 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
279 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
283 Unique<VkCommandPool> copyPool(createCommandPool(vkd, dev, ©PoolCreateInfo));
285 const VkCommandBufferAllocateInfo copyBufferCreateInfo =
287 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
290 VK_COMMAND_BUFFER_LEVEL_PRIMARY,
294 Unique<VkCommandBuffer> copyBuffer(allocateCommandBuffer(vkd, dev, ©BufferCreateInfo));
296 std::vector<VkBufferImageCopy> copyRegions;
298 deUint8* const bufMapPtr = reinterpret_cast<deUint8*>(bufMem->getHostPtr());
299 deUint8* bufCurPtr = bufMapPtr;
301 for (int level = 0; level < imParams.levels; ++level)
303 const IVec3 curLevelSize = pba[level].getSize();
305 const std::size_t copySize =
306 getPixelSize(mapVkFormat(imParams.format))
307 * curLevelSize[0] * curLevelSize[1] * curLevelSize[2]
308 * imParams.arrayLayers;
310 deMemcpy(bufCurPtr, pba[level].getDataPtr(), copySize);
312 flushMappedMemoryRange(vkd, dev, bufMem->getMemory(), bufMem->getOffset() + (bufCurPtr - bufMapPtr), copySize);
314 const VkImageSubresourceLayers curSubresource =
316 VK_IMAGE_ASPECT_COLOR_BIT,
319 (deUint32)imParams.arrayLayers
322 const VkBufferImageCopy curRegion =
324 (VkDeviceSize) (bufCurPtr - bufMapPtr),
329 {(deUint32)curLevelSize[0], (deUint32)curLevelSize[1], (deUint32)curLevelSize[2]}
332 copyRegions.push_back(curRegion);
334 bufCurPtr += copySize;
337 const VkCommandBufferBeginInfo beginInfo =
339 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
341 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
345 VK_CHECK(vkd.beginCommandBuffer(copyBuffer.get(), &beginInfo));
347 const VkImageSubresourceRange imMemBarSubRange =
349 VK_IMAGE_ASPECT_COLOR_BIT,
351 (deUint32)imParams.levels,
353 (deUint32)imParams.arrayLayers
356 VkImageMemoryBarrier imMemBar =
358 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
361 VK_ACCESS_TRANSFER_WRITE_BIT,
362 VK_IMAGE_LAYOUT_UNDEFINED,
363 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
364 VK_QUEUE_FAMILY_IGNORED,
365 VK_QUEUE_FAMILY_IGNORED,
370 VkBufferMemoryBarrier bufMemBar =
372 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
374 VK_ACCESS_HOST_WRITE_BIT,
375 VK_ACCESS_TRANSFER_READ_BIT,
376 VK_QUEUE_FAMILY_IGNORED,
377 VK_QUEUE_FAMILY_IGNORED,
383 vkd.cmdPipelineBarrier(copyBuffer.get(),
384 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
385 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
394 vkd.cmdCopyBufferToImage(copyBuffer.get(),
397 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
398 (deUint32)copyRegions.size(),
401 imMemBar.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
402 imMemBar.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
403 imMemBar.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
404 imMemBar.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
406 vkd.cmdPipelineBarrier(copyBuffer.get(),
407 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
408 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
417 VK_CHECK(vkd.endCommandBuffer(copyBuffer.get()));
419 const VkSubmitInfo copySubmitInfo =
421 VK_STRUCTURE_TYPE_SUBMIT_INFO,
432 VK_CHECK(vkd.queueSubmit(ctx.getUniversalQueue(), 1, ©SubmitInfo, 0));
433 VK_CHECK(vkd.queueWaitIdle(ctx.getUniversalQueue()));
438 std::vector<ConstPixelBufferAccess> pba;
439 ImageViewParameters imParams;
440 SamplerParameters samplerParams;
441 SampleLookupSettings sampleLookupSettings;
442 glu::ShaderType shaderType;
445 VkSamplerCreateInfo mapSamplerCreateInfo (const SamplerParameters& samplerParams)
447 VkSamplerCreateInfo samplerCreateInfo =
449 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // sType
452 samplerParams.magFilter, // magFilter
453 samplerParams.minFilter, // minFilter
454 samplerParams.mipmapFilter, // mipmapMode
455 samplerParams.wrappingModeU, // addressModeU
456 samplerParams.wrappingModeV, // addressModeV
457 samplerParams.wrappingModeW, // addressMoveW
458 samplerParams.lodBias, // mipLodBias
459 VK_FALSE, // anisotropyEnable
460 1.0f, // maxAnisotropy
461 VK_FALSE, // compareEnable
462 VK_COMPARE_OP_NEVER, // compareOp
463 samplerParams.minLod, // minLod
464 samplerParams.maxLod, // maxLod
465 samplerParams.borderColor, // borderColor
466 samplerParams.isUnnormalized ? VK_TRUE : VK_FALSE, // unnormalizedCoordinates
469 if (samplerParams.isCompare)
471 samplerCreateInfo.compareEnable = VK_TRUE;
473 DE_FATAL("Not implemented");
476 return samplerCreateInfo;
479 VkImageType mapImageType (ImgDim dim)
486 imType = VK_IMAGE_TYPE_1D;
491 imType = VK_IMAGE_TYPE_2D;
495 imType = VK_IMAGE_TYPE_3D;
499 imType = VK_IMAGE_TYPE_LAST;
506 VkImageViewType mapImageViewType (const ImageViewParameters& imParams)
508 VkImageViewType imViewType;
510 if (imParams.isArrayed)
512 switch (imParams.dim)
515 imViewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
519 imViewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
523 imViewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
527 imViewType = VK_IMAGE_VIEW_TYPE_LAST;
533 switch (imParams.dim)
536 imViewType = VK_IMAGE_VIEW_TYPE_1D;
540 imViewType = VK_IMAGE_VIEW_TYPE_2D;
544 imViewType = VK_IMAGE_VIEW_TYPE_3D;
548 imViewType = VK_IMAGE_VIEW_TYPE_CUBE;
552 imViewType = VK_IMAGE_VIEW_TYPE_LAST;
563 virtual ~DataGenerator (void) {}
565 virtual bool generate (void) = 0;
567 virtual std::vector<ConstPixelBufferAccess> getPba (void) const = 0;
568 virtual std::vector<SampleArguments> getSampleArgs (void) const = 0;
571 DataGenerator (void) {}
574 class TextureFilteringTestInstance : public TestInstance
577 TextureFilteringTestInstance (Context& ctx,
578 const TestCaseData& testCaseData,
579 ShaderExecutor& shaderExecutor,
580 de::MovePtr<DataGenerator> gen)
583 , m_imParams (testCaseData.imParams)
584 , m_samplerParams (testCaseData.samplerParams)
585 , m_sampleLookupSettings (testCaseData.sampleLookupSettings)
586 , m_shaderExecutor (shaderExecutor)
588 , m_vki (m_ctx.getInstanceInterface())
589 , m_vkd (m_ctx.getDeviceInterface())
590 , m_instance (m_ctx.getInstance())
591 , m_physicalDevice (m_ctx.getPhysicalDevice())
592 , m_device (m_ctx.getDevice())
593 , m_uqfi (m_ctx.getUniversalQueueFamilyIndex())
594 , m_pba (testCaseData.pba)
595 , m_gen (gen.release())
597 for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
599 DE_ASSERT(m_imParams.size[compNdx] > 0);
602 m_imExtent.width = m_imParams.size[0];
603 m_imExtent.height = m_imParams.size[1];
604 m_imExtent.depth = m_imParams.size[2];
607 virtual TestStatus iterate (void)
613 TestStatus runTest (void);
614 bool isSupported (void);
615 void createResources (void);
619 tcu::Sampler mapTcuSampler (void);
621 const ImageViewParameters& m_imParams;
622 const SamplerParameters& m_samplerParams;
623 const SampleLookupSettings& m_sampleLookupSettings;
625 std::vector<SampleArguments> m_sampleArguments;
626 deUint32 m_numSamples;
628 ShaderExecutor& m_shaderExecutor;
630 const InstanceInterface& m_vki;
631 const DeviceInterface& m_vkd;
632 VkInstance m_instance;
633 VkPhysicalDevice m_physicalDevice;
637 VkExtent3D m_imExtent;
642 de::MovePtr<Allocation> m_imAllocation;
644 Move<VkImageView> m_imView;
645 Move<VkSampler> m_sampler;
647 std::vector<ConstPixelBufferAccess> m_pba;
648 de::MovePtr<DataGenerator> m_gen;
650 std::vector<Vec4> m_resultSamples;
651 std::vector<Vec4> m_resultCoords;
654 TestStatus TextureFilteringTestInstance::runTest (void)
658 TCU_THROW(NotSupportedError, "Unsupported combination of filtering and image format");
661 TCU_CHECK(m_gen->generate());
662 m_pba = m_gen->getPba();
664 m_sampleArguments = m_gen->getSampleArgs();
665 m_numSamples = (deUint32)m_sampleArguments.size();
668 initializeImage(m_ctx, m_im.get(), &m_pba[0], m_imParams);
670 m_shaderExecutor.addSamplerUniform(0, m_imView.get(), m_sampler.get());
672 deUint64 startTime, endTime;
674 startTime = deGetMicroseconds();
676 endTime = deGetMicroseconds();
678 m_ctx.getTestContext().getLog() << TestLog::Message
679 << "Execution time: "
680 << endTime - startTime
682 << TestLog::EndMessage;
684 startTime = deGetMicroseconds();
685 bool result = verify();
686 endTime = deGetMicroseconds();
688 m_ctx.getTestContext().getLog() << TestLog::Message
689 << "Verification time: "
690 << endTime - startTime
692 << TestLog::EndMessage;
696 return TestStatus::pass("Success");
700 // \todo [2016-06-24 collinbaker] Print report if verification fails
701 return TestStatus::fail("Verification failed");
705 bool TextureFilteringTestInstance::verify (void)
707 // \todo [2016-06-24 collinbaker] Handle cubemaps
709 m_coordBits = (deUint8) m_ctx.getDeviceProperties().limits.subTexelPrecisionBits;
710 m_mipmapBits = (deUint8) m_ctx.getDeviceProperties().limits.mipmapPrecisionBits;
712 SampleVerifier verifier(m_imParams,
714 m_sampleLookupSettings,
719 const int maxPrintedFailures = 5;
722 for (deUint32 sampleNdx = 0; sampleNdx < m_numSamples; ++sampleNdx)
724 if (!verifier.verifySample(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx]))
726 if (failCount++ < maxPrintedFailures)
728 // Re-run with report logging
730 verifier.verifySampleReport(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx], report);
732 m_ctx.getTestContext().getLog()
733 << TestLog::Section("Failed sample", "Failed sample")
735 << "Sample " << sampleNdx << ".\n"
736 << "\tCoordinate: " << m_sampleArguments[sampleNdx].coord << "\n"
737 << "\tLOD: " << m_sampleArguments[sampleNdx].lod << "\n"
738 << "\tGPU Result: " << m_resultSamples[sampleNdx] << "\n\n"
739 << "Failure report:\n" << report << "\n"
740 << TestLog::EndMessage
741 << TestLog::EndSection;
746 m_ctx.getTestContext().getLog()
748 << "Passed " << m_numSamples - failCount << " out of " << m_numSamples << "."
749 << TestLog::EndMessage;
751 return failCount == 0;
754 void TextureFilteringTestInstance::execute (void)
756 std::vector<float> coords, layers, dRefs, dPdxs, dPdys, lods;
758 for (deUint32 ndx = 0; ndx < m_numSamples; ++ndx)
760 const SampleArguments& sampleArgs = m_sampleArguments[ndx];
762 for (deUint8 compNdx = 0; compNdx < 4; ++compNdx)
764 coords.push_back(sampleArgs.coord[compNdx]);
765 dPdxs .push_back(sampleArgs.dPdx[compNdx]);
766 dPdys .push_back(sampleArgs.dPdy[compNdx]);
769 layers.push_back(sampleArgs.layer);
770 dRefs .push_back(sampleArgs.dRef);
771 lods .push_back(sampleArgs.lod);
774 const void* inputs[6] =
776 reinterpret_cast<const void*>(&coords[0]),
777 reinterpret_cast<const void*>(&layers[0]),
778 reinterpret_cast<const void*>(&dRefs[0]),
779 reinterpret_cast<const void*>(&dPdxs[0]),
780 reinterpret_cast<const void*>(&dPdys[0]),
781 reinterpret_cast<const void*>(&lods[0])
784 // Staging buffers; data will be copied into vectors of Vec4
785 // \todo [2016-06-24 collinbaker] Figure out if I actually need to
786 // use staging buffers
787 std::vector<float> resultSamplesTemp(m_numSamples * 4);
788 std::vector<float> resultCoordsTemp (m_numSamples * 4);
792 reinterpret_cast<void*>(&resultSamplesTemp[0]),
793 reinterpret_cast<void*>(&resultCoordsTemp[0])
796 m_shaderExecutor.execute(m_ctx, m_numSamples, inputs, outputs);
798 m_resultSamples.resize(m_numSamples);
799 m_resultCoords .resize(m_numSamples);
801 for (deUint32 ndx = 0; ndx < m_numSamples; ++ndx)
803 m_resultSamples[ndx] = Vec4(resultSamplesTemp[4 * ndx + 0],
804 resultSamplesTemp[4 * ndx + 1],
805 resultSamplesTemp[4 * ndx + 2],
806 resultSamplesTemp[4 * ndx + 3]);
808 m_resultCoords [ndx] = Vec4(resultCoordsTemp [4 * ndx + 0],
809 resultCoordsTemp [4 * ndx + 1],
810 resultCoordsTemp [4 * ndx + 2],
811 resultCoordsTemp [4 * ndx + 3]);
815 void TextureFilteringTestInstance::createResources (void)
819 const VkImageCreateFlags imCreateFlags =
820 (m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
822 const VkImageCreateInfo imCreateInfo =
824 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
826 imCreateFlags, // flags
827 mapImageType(m_imParams.dim), // imageType
828 m_imParams.format, // format
829 m_imExtent, // extent
830 (deUint32)m_imParams.levels, // mipLevels
831 (deUint32)m_imParams.arrayLayers, // arrayLayers
832 VK_SAMPLE_COUNT_1_BIT, // samples
833 VK_IMAGE_TILING_OPTIMAL, // tiling
834 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, // usage
835 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
836 1, // queueFamilyIndexCount
837 &m_uqfi, // pQueueFamilyIndices
838 VK_IMAGE_LAYOUT_UNDEFINED // initialLayout
841 m_im = createImage(m_vkd, m_device, &imCreateInfo);
843 // Allocate memory for image
845 VkMemoryRequirements imMemReq;
846 m_vkd.getImageMemoryRequirements(m_device, m_im.get(), &imMemReq);
848 m_imAllocation = m_ctx.getDefaultAllocator().allocate(imMemReq, MemoryRequirement::Any);
849 VK_CHECK(m_vkd.bindImageMemory(m_device, m_im.get(), m_imAllocation->getMemory(), m_imAllocation->getOffset()));
851 // Create VkImageView
853 // \todo [2016-06-23 collinbaker] Pick aspectMask based on image type (i.e. support depth and/or stencil images)
854 VkImageSubresourceRange imViewSubresourceRange =
856 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
858 (deUint32)m_imParams.levels, // levelCount
860 (deUint32)m_imParams.arrayLayers // layerCount
863 if (m_imParams.dim == IMG_DIM_CUBE)
865 imViewSubresourceRange.layerCount *= 6;
868 const VkComponentMapping imViewCompMap =
870 VK_COMPONENT_SWIZZLE_R,
871 VK_COMPONENT_SWIZZLE_G,
872 VK_COMPONENT_SWIZZLE_B,
873 VK_COMPONENT_SWIZZLE_A
876 const VkImageViewCreateInfo imViewCreateInfo =
878 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType
882 mapImageViewType(m_imParams), // viewType
883 m_imParams.format, // format
884 imViewCompMap, // components
885 imViewSubresourceRange // subresourceRange
888 m_imView = createImageView(m_vkd, m_device, &imViewCreateInfo);
892 const VkSamplerCreateInfo samplerCreateInfo = mapSamplerCreateInfo(m_samplerParams);
893 m_sampler = createSampler(m_vkd, m_device, &samplerCreateInfo);
896 bool TextureFilteringTestInstance::isSupported (void)
898 const VkImageCreateFlags imCreateFlags =
899 (m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
901 VkImageFormatProperties imFormatProperties;
902 VkFormatProperties formatProperties;
904 m_vki.getPhysicalDeviceImageFormatProperties(m_physicalDevice,
906 mapImageType(m_imParams.dim),
907 VK_IMAGE_TILING_OPTIMAL,
908 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
910 &imFormatProperties);
912 m_vki.getPhysicalDeviceFormatProperties( m_physicalDevice,
916 // \todo [2016-06-23 collinbaker] Check image parameters against imFormatProperties
918 VkFormatFeatureFlags reqImFeatures = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
920 if (m_samplerParams.minFilter == VK_FILTER_LINEAR ||
921 m_samplerParams.magFilter == VK_FILTER_LINEAR ||
922 m_samplerParams.mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
924 reqImFeatures |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
927 return (formatProperties.optimalTilingFeatures & reqImFeatures) == reqImFeatures;
930 class TextureFilteringTestCase : public TestCase
933 TextureFilteringTestCase (tcu::TestContext& testCtx,
935 const char* description)
936 : TestCase(testCtx, name, description)
942 virtual void initPrograms (vk::SourceCollections& programCollection) const
944 DE_ASSERT(m_executor);
945 m_executor->setShaderSources(programCollection);
948 virtual de::MovePtr<DataGenerator> createGenerator (void) const = 0;
950 virtual TestInstance* createInstance (Context& ctx) const
952 return new TextureFilteringTestInstance(ctx, m_testCaseData, *m_executor, createGenerator());
956 de::MovePtr<ShaderExecutor> m_executor;
957 TestCaseData m_testCaseData;
960 void TextureFilteringTestCase::init (void)
962 ShaderSpec shaderSpec;
963 shaderSpec.source = genLookupCode(m_testCaseData.imParams,
964 m_testCaseData.samplerParams,
965 m_testCaseData.sampleLookupSettings);
966 shaderSpec.source += "\nsampledCoord = coord;";
968 shaderSpec.outputs.push_back(Symbol("result", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
969 shaderSpec.outputs.push_back(Symbol("sampledCoord", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
970 shaderSpec.inputs .push_back(Symbol("coord", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
971 shaderSpec.inputs .push_back(Symbol("layer", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
972 shaderSpec.inputs .push_back(Symbol("dRef", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
973 shaderSpec.inputs .push_back(Symbol("dPdx", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
974 shaderSpec.inputs .push_back(Symbol("dPdy", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
975 shaderSpec.inputs .push_back(Symbol("lod", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
977 shaderSpec.globalDeclarations = "layout(set=0, binding=0) uniform highp ";
978 shaderSpec.globalDeclarations += genSamplerDeclaration(m_testCaseData.imParams,
979 m_testCaseData.samplerParams);
980 shaderSpec.globalDeclarations += " testSampler;";
982 m_executor = de::MovePtr<ShaderExecutor>(createExecutor(m_testCaseData.shaderType, shaderSpec));
983 DE_ASSERT(m_executor);
985 m_testCtx.getLog() << *m_executor;
988 class Texture2DGradientTestCase : public TextureFilteringTestCase
991 Texture2DGradientTestCase (TestContext& testCtx,
994 TextureFormat format,
998 VkSamplerMipmapMode mipmapFilter,
999 VkSamplerAddressMode wrappingMode,
1000 bool useDerivatives)
1002 : TextureFilteringTestCase (testCtx, name, desc)
1004 , m_dimensions (dimensions)
1005 , m_magFilter (magFilter)
1006 , m_minFilter (minFilter)
1007 , m_mipmapFilter (mipmapFilter)
1008 , m_wrappingMode (wrappingMode)
1009 , m_useDerivatives (useDerivatives)
1011 m_testCaseData = genTestCaseData();
1018 virtual de::MovePtr<DataGenerator> createGenerator (void) const;
1020 TestCaseData genTestCaseData()
1024 SampleLookupSettings sampleLookupSettings =
1026 m_useDerivatives ? LOOKUP_LOD_MODE_DERIVATIVES : LOOKUP_LOD_MODE_LOD, // lookupLodMode
1027 false, // hasLodBias
1028 false, // isProjective
1031 SamplerParameters samplerParameters =
1033 m_magFilter, // magFilter
1034 m_minFilter, // minFilter
1035 m_mipmapFilter, // mipmapFilter
1036 m_wrappingMode, // wrappingModeU
1037 m_wrappingMode, // wrappingModeV
1038 m_wrappingMode, // wrappingModeW
1039 VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE, // borderColor
1043 false, // isUnnormalized
1047 deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_dimensions[0],
1050 ImageViewParameters imParameters =
1053 mapTextureFormat(m_format), // format
1054 m_dimensions, // size
1055 numLevels, // levels
1062 std::vector<ConstPixelBufferAccess>(),
1065 sampleLookupSettings,
1066 glu::SHADERTYPE_FRAGMENT
1073 TextureFormat m_format;
1075 VkFilter m_magFilter;
1076 VkFilter m_minFilter;
1077 VkSamplerMipmapMode m_mipmapFilter;
1078 VkSamplerAddressMode m_wrappingMode;
1079 bool m_useDerivatives;
1082 class Texture2DGradientTestCase::Generator : public DataGenerator
1085 Generator (const Texture2DGradientTestCase* testCase) : m_testCase(testCase) {}
1087 virtual ~Generator (void)
1089 delete m_tex.release();
1092 virtual bool generate (void)
1094 m_tex = de::MovePtr<Texture2D>(new Texture2D(m_testCase->m_format,
1095 m_testCase->m_dimensions[0],
1096 m_testCase->m_dimensions[1]));
1098 deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_testCase->m_dimensions[0],
1099 m_testCase->m_dimensions[1])));
1101 TextureFormatInfo fmtInfo = getTextureFormatInfo(m_testCase->m_format);
1103 Vec4 cBias = fmtInfo.valueMin;
1104 Vec4 cScale = fmtInfo.valueMax - fmtInfo.valueMin;
1106 for (deUint8 levelNdx = 0; levelNdx < numLevels; ++levelNdx)
1108 Vec4 gMin = Vec4(0.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
1109 Vec4 gMax = Vec4(1.0f, 1.0f, 1.0f, 0.0f) * cScale + cBias;
1111 m_tex->allocLevel(levelNdx);
1112 fillWithComponentGradients(m_tex->getLevel(levelNdx), gMin, gMax);
1118 virtual std::vector<ConstPixelBufferAccess> getPba (void) const
1120 std::vector<ConstPixelBufferAccess> pba;
1122 const deUint8 numLevels = (deUint8) m_tex->getNumLevels();
1124 for (deUint8 levelNdx = 0; levelNdx < numLevels; ++levelNdx)
1126 pba.push_back(m_tex->getLevel(levelNdx));
1132 virtual std::vector<SampleArguments> getSampleArgs (void) const
1134 std::vector<SampleArguments> args;
1136 if (m_testCase->m_useDerivatives)
1145 {Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(0.0f, 0.0f, 0.0f, 0.0f)},
1146 {Vec4(1.0f, 1.0f, 1.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f)},
1147 {Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f)},
1148 {Vec4(1.0f, 1.0f, 1.0f, 0.0f), Vec4(0.0f, 0.0f, 0.0f, 0.0f)},
1149 {Vec4(2.0f, 2.0f, 2.0f, 0.0f), Vec4(2.0f, 2.0f, 2.0f, 0.0f)}
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 derivNdx = 0; derivNdx < DE_LENGTH_OF_ARRAY(derivativePairs); ++derivNdx)
1158 SampleArguments cur;
1159 cur.coord = Vec4((float)i / (float)(2 * m_testCase->m_dimensions[0]),
1160 (float)j / (float)(2 * m_testCase->m_dimensions[1]),
1162 cur.dPdx = derivativePairs[derivNdx].dPdx;
1163 cur.dPdy = derivativePairs[derivNdx].dPdy;
1165 args.push_back(cur);
1172 const float lodList[] = {-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0};
1174 for (deInt32 i = 0; i < 2 * m_testCase->m_dimensions[0] + 1; ++i)
1176 for (deInt32 j = 0; j < 2 * m_testCase->m_dimensions[1] + 1; ++j)
1178 for (deUint32 lodNdx = 0; lodNdx < DE_LENGTH_OF_ARRAY(lodList); ++lodNdx)
1180 SampleArguments cur;
1181 cur.coord = Vec4((float)i / (float)(2 * m_testCase->m_dimensions[0]),
1182 (float)j / (float)(2 * m_testCase->m_dimensions[1]),
1184 cur.lod = lodList[lodNdx];
1186 args.push_back(cur);
1196 const Texture2DGradientTestCase* m_testCase;
1197 de::MovePtr<Texture2D> m_tex;
1200 de::MovePtr<DataGenerator> Texture2DGradientTestCase::createGenerator (void) const
1202 return de::MovePtr<DataGenerator>(new Generator(this));
1205 TestCaseGroup* create2DFormatTests (TestContext& testCtx)
1207 de::MovePtr<TestCaseGroup> tests(
1208 new TestCaseGroup(testCtx, "formats", "Various image formats"));
1210 VkFormat formats[] =
1212 VK_FORMAT_B4G4R4A4_UNORM_PACK16,
1213 VK_FORMAT_R5G6B5_UNORM_PACK16,
1214 VK_FORMAT_A1R5G5B5_UNORM_PACK16,
1217 VK_FORMAT_R8G8_UNORM,
1218 VK_FORMAT_R8G8_SNORM,
1219 VK_FORMAT_R8G8B8A8_UNORM,
1220 VK_FORMAT_R8G8B8A8_SNORM,
1221 // VK_FORMAT_R8G8B8A8_SRGB,
1222 VK_FORMAT_B8G8R8A8_UNORM,
1223 // VK_FORMAT_B8G8R8A8_SRGB,
1224 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1225 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
1226 // VK_FORMAT_A8B8G8R8_SRGB_PACK32,
1227 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1228 VK_FORMAT_R16_SFLOAT,
1229 VK_FORMAT_R16G16_SFLOAT,
1230 VK_FORMAT_R16G16B16A16_SFLOAT,
1231 VK_FORMAT_R32_SFLOAT,
1232 VK_FORMAT_R32G32_SFLOAT,
1233 VK_FORMAT_R32G32B32A32_SFLOAT,
1234 // VK_FORMAT_B10G11R11_UFLOAT_PACK32,
1235 // VK_FORMAT_E5B9G9R9_UFLOAT_PACK32
1238 const IVec3 size(32, 32, 1);
1240 for (deUint32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
1242 std::string prefix = de::toLower(std::string(getFormatName(formats[formatNdx])).substr(10));
1244 Texture2DGradientTestCase* testCaseNearest =
1245 new Texture2DGradientTestCase(
1247 (prefix + "_nearest").c_str(),
1249 mapVkFormat(formats[formatNdx]),
1253 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1254 VK_SAMPLER_ADDRESS_MODE_REPEAT,
1257 tests->addChild(testCaseNearest);
1259 Texture2DGradientTestCase* testCaseLinear =
1260 new Texture2DGradientTestCase(
1262 (prefix + "_linear").c_str(),
1264 mapVkFormat(formats[formatNdx]),
1268 VK_SAMPLER_MIPMAP_MODE_LINEAR,
1269 VK_SAMPLER_ADDRESS_MODE_REPEAT,
1272 tests->addChild(testCaseLinear);
1275 return tests.release();
1278 TestCaseGroup* create2DDerivTests (TestContext& testCtx)
1280 de::MovePtr<TestCaseGroup> tests(
1281 new TestCaseGroup(testCtx, "derivatives", "Explicit derivative tests"));
1283 const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1284 const VkSamplerAddressMode wrappingMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1285 const IVec3 size = IVec3(16, 16, 1);
1287 const VkFilter filters[2] =
1293 const VkSamplerMipmapMode mipmapFilters[2] =
1295 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1296 VK_SAMPLER_MIPMAP_MODE_LINEAR,
1299 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(filters); ++magFilterNdx)
1301 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(filters); ++minFilterNdx)
1303 for (int mipmapFilterNdx = 0; mipmapFilterNdx < DE_LENGTH_OF_ARRAY(mipmapFilters); ++mipmapFilterNdx)
1305 std::ostringstream caseName;
1307 switch (filters[magFilterNdx])
1309 case VK_FILTER_NEAREST:
1310 caseName << "nearest";
1313 case VK_FILTER_LINEAR:
1314 caseName << "linear";
1321 switch (filters[minFilterNdx])
1323 case VK_FILTER_NEAREST:
1324 caseName << "_nearest";
1327 case VK_FILTER_LINEAR:
1328 caseName << "_linear";
1335 caseName << "_mipmap";
1337 switch (mipmapFilters[mipmapFilterNdx])
1339 case VK_SAMPLER_MIPMAP_MODE_NEAREST:
1340 caseName << "_nearest";
1343 case VK_SAMPLER_MIPMAP_MODE_LINEAR:
1344 caseName << "_linear";
1351 Texture2DGradientTestCase* testCase =
1352 new Texture2DGradientTestCase(
1354 caseName.str().c_str(),
1356 mapVkFormat(format),
1358 filters[magFilterNdx],
1359 filters[minFilterNdx],
1360 mipmapFilters[mipmapFilterNdx],
1364 tests->addChild(testCase);
1369 return tests.release();
1372 TestCaseGroup* create2DSizeTests (TestContext& testCtx)
1374 de::MovePtr<TestCaseGroup> tests(
1375 new TestCaseGroup(testCtx, "sizes", "Various size and filtering combinations"));
1377 const VkFilter filters[2] =
1383 const VkSamplerMipmapMode mipmapFilters[2] =
1385 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1386 VK_SAMPLER_MIPMAP_MODE_LINEAR
1389 const VkSamplerAddressMode wrappingModes[2] =
1391 VK_SAMPLER_ADDRESS_MODE_REPEAT,
1392 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE
1409 for (deUint32 sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1411 for (deUint32 magFilterNdx = 0; magFilterNdx < 2; ++magFilterNdx)
1413 for (deUint32 minFilterNdx = 0; minFilterNdx < 2; ++minFilterNdx)
1415 for (deUint32 mipmapFilterNdx = 0; mipmapFilterNdx < 2; ++mipmapFilterNdx)
1417 for (deUint32 wrappingModeNdx = 0; wrappingModeNdx < 2; ++wrappingModeNdx)
1419 std::ostringstream caseName;
1421 caseName << sizes[sizeNdx][0] << "x" << sizes[sizeNdx][1];
1423 switch (filters[magFilterNdx])
1425 case VK_FILTER_NEAREST:
1426 caseName << "_nearest";
1429 case VK_FILTER_LINEAR:
1430 caseName << "_linear";
1437 switch (filters[minFilterNdx])
1439 case VK_FILTER_NEAREST:
1440 caseName << "_nearest";
1443 case VK_FILTER_LINEAR:
1444 caseName << "_linear";
1451 switch (mipmapFilters[mipmapFilterNdx])
1453 case VK_SAMPLER_MIPMAP_MODE_NEAREST:
1454 caseName << "_mipmap_nearest";
1457 case VK_SAMPLER_MIPMAP_MODE_LINEAR:
1458 caseName << "_mipmap_linear";
1465 switch (wrappingModes[wrappingModeNdx])
1467 case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
1468 caseName << "_clamp";
1471 case VK_SAMPLER_ADDRESS_MODE_REPEAT:
1472 caseName << "_repeat";
1479 Texture2DGradientTestCase* testCase =
1480 new Texture2DGradientTestCase(
1482 caseName.str().c_str(),
1484 mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM),
1486 filters[magFilterNdx],
1487 filters[minFilterNdx],
1488 mipmapFilters[mipmapFilterNdx],
1489 wrappingModes[wrappingModeNdx],
1492 tests->addChild(testCase);
1499 return tests.release();
1502 TestCaseGroup* create2DTests (TestContext& testCtx)
1504 de::MovePtr<TestCaseGroup> tests(
1505 new TestCaseGroup(testCtx, "2d", "2D Image filtering tests"));
1507 tests->addChild(create2DSizeTests(testCtx));
1508 tests->addChild(create2DFormatTests(testCtx));
1509 tests->addChild(create2DDerivTests(testCtx));
1511 return tests.release();
1516 TestCaseGroup* createExplicitLodTests (TestContext& testCtx)
1518 de::MovePtr<TestCaseGroup> tests(
1519 new TestCaseGroup(testCtx, "explicit_lod", "Texture filtering with explicit LOD"));
1521 tests->addChild(create2DTests(testCtx));
1523 return tests.release();
1526 } // texture_filtering