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 "deUniquePtr.hpp"
55 namespace texture_filtering
65 using namespace shaderexecutor;
67 string genSamplerDeclaration(const ImageViewParameters& imParams,
68 const SamplerParameters& samplerParams)
70 string result = "sampler";
90 if (imParams.isArrayed)
95 if (samplerParams.isCompare)
103 string genLookupCode(const ImageViewParameters& imParams,
104 const SamplerParameters& samplerParams,
105 const SampleLookupSettings& lookupSettings)
109 switch (imParams.dim)
128 DE_ASSERT(dim >= 1 && dim <= 3);
130 int numCoordComp = dim;
132 if (lookupSettings.isProjective)
137 int numArgComp = numCoordComp;
138 bool hasSeparateCompare = false;
140 if (imParams.isArrayed)
142 DE_ASSERT(!lookupSettings.isProjective && "Can't do a projective lookup on an arrayed image!");
147 if (samplerParams.isCompare && numCoordComp == 4)
149 hasSeparateCompare = true;
151 else if (samplerParams.isCompare)
156 // Build coordinate input to texture*() function
159 arg += (char) (numArgComp + '0');
161 arg += (char) (numCoordComp + '0');
164 int numZero = numArgComp - numCoordComp;
166 if (imParams.isArrayed)
172 if (samplerParams.isCompare && !hasSeparateCompare)
178 for (int ndx = 0; ndx < numZero; ++ndx)
185 // Build call to texture*() function
189 code += "result = texture";
191 if (lookupSettings.isProjective)
196 if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
200 else if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_LOD)
205 code += "(testSampler, ";
208 if (samplerParams.isCompare && hasSeparateCompare)
213 if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
215 code += ", dPdx, dPdy";
217 else if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_LOD)
227 void initializeImage(Context& ctx, VkImage im, const ConstPixelBufferAccess* pba, ImageViewParameters imParams)
229 const DeviceInterface& vkd = ctx.getDeviceInterface();
230 const VkDevice dev = ctx.getDevice();
231 const deUint32 uqfi = ctx.getUniversalQueueFamilyIndex();
233 const VkDeviceSize bufSize =
234 getPixelSize(mapVkFormat(imParams.format))
235 * imParams.arrayLayers
241 const VkBufferCreateInfo bufCreateInfo =
243 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
247 VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage
248 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
249 1, // queueFamilyIndexCount
250 &uqfi // pQueueFamilyIndices
253 Unique<VkBuffer> buf(createBuffer(vkd, dev, &bufCreateInfo));
255 VkMemoryRequirements bufMemReq;
256 vkd.getBufferMemoryRequirements(dev, buf.get(), &bufMemReq);
258 de::UniquePtr<Allocation> bufMem(ctx.getDefaultAllocator().allocate(bufMemReq, MemoryRequirement::HostVisible));
259 VK_CHECK(vkd.bindBufferMemory(dev, buf.get(), bufMem->getMemory(), bufMem->getOffset()));
261 const VkCommandPoolCreateInfo copyPoolCreateInfo =
263 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
265 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
269 Unique<VkCommandPool> copyPool(createCommandPool(vkd, dev, ©PoolCreateInfo));
271 const VkCommandBufferAllocateInfo copyBufferCreateInfo =
273 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
276 VK_COMMAND_BUFFER_LEVEL_PRIMARY,
280 Unique<VkCommandBuffer> copyBuffer(allocateCommandBuffer(vkd, dev, ©BufferCreateInfo));
282 std::vector<VkBufferImageCopy> copyRegions;
284 deUint8* const bufMapPtr = reinterpret_cast<deUint8*>(bufMem->getHostPtr());
285 deUint8* bufCurPtr = bufMapPtr;
287 for (int level = 0; level < imParams.levels; ++level)
289 const IVec3 curLevelSize = pba[level].getSize();
291 const std::size_t copySize =
292 getPixelSize(mapVkFormat(imParams.format))
293 * curLevelSize[0] * curLevelSize[1] * curLevelSize[2]
294 * imParams.arrayLayers;
296 deMemcpy(bufCurPtr, pba[level].getDataPtr(), copySize);
298 flushMappedMemoryRange(vkd, dev, bufMem->getMemory(), bufMem->getOffset() + (bufCurPtr - bufMapPtr), copySize);
300 const VkImageSubresourceLayers curSubresource =
302 VK_IMAGE_ASPECT_COLOR_BIT,
305 (deUint32) imParams.arrayLayers
308 const VkBufferImageCopy curRegion =
310 (VkDeviceSize) (bufCurPtr - bufMapPtr),
315 {(deUint32) curLevelSize[0], (deUint32) curLevelSize[1], (deUint32) curLevelSize[2]}
318 copyRegions.push_back(curRegion);
320 bufCurPtr += copySize;
323 const VkCommandBufferBeginInfo beginInfo =
325 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
327 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
331 VK_CHECK(vkd.beginCommandBuffer(copyBuffer.get(), &beginInfo));
333 const VkImageSubresourceRange imMemBarSubRange =
335 VK_IMAGE_ASPECT_COLOR_BIT,
342 VkImageMemoryBarrier imMemBar =
344 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
347 VK_ACCESS_TRANSFER_WRITE_BIT,
348 VK_IMAGE_LAYOUT_UNDEFINED,
349 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
350 VK_QUEUE_FAMILY_IGNORED,
351 VK_QUEUE_FAMILY_IGNORED,
356 VkBufferMemoryBarrier bufMemBar =
358 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
360 VK_ACCESS_HOST_WRITE_BIT,
361 VK_ACCESS_TRANSFER_READ_BIT,
362 VK_QUEUE_FAMILY_IGNORED,
363 VK_QUEUE_FAMILY_IGNORED,
369 vkd.cmdPipelineBarrier(copyBuffer.get(),
370 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
371 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
380 vkd.cmdCopyBufferToImage(copyBuffer.get(),
383 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
384 (deUint32) copyRegions.size(),
387 imMemBar.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
388 imMemBar.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
389 imMemBar.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
390 imMemBar.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
392 vkd.cmdPipelineBarrier(copyBuffer.get(),
393 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
394 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
403 VK_CHECK(vkd.endCommandBuffer(copyBuffer.get()));
405 const VkSubmitInfo copySubmitInfo =
407 VK_STRUCTURE_TYPE_SUBMIT_INFO,
418 VK_CHECK(vkd.queueSubmit(ctx.getUniversalQueue(), 1, ©SubmitInfo, 0));
419 VK_CHECK(vkd.queueWaitIdle(ctx.getUniversalQueue()));
424 std::vector<ConstPixelBufferAccess> pba;
425 ImageViewParameters imParams;
426 SamplerParameters samplerParams;
427 SampleLookupSettings sampleLookupSettings;
428 const SampleArguments* sampleArguments;
430 glu::ShaderType shaderType;
433 VkSamplerCreateInfo mapSamplerCreateInfo (const SamplerParameters& samplerParams)
435 VkSamplerCreateInfo samplerCreateInfo =
437 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // sType
440 samplerParams.magFilter, // magFilter
441 samplerParams.minFilter, // minFilter
442 samplerParams.mipmapFilter, // mipmapMode
443 samplerParams.wrappingModeU, // addressModeU
444 samplerParams.wrappingModeV, // addressModeV
445 samplerParams.wrappingModeW, // addressMoveW
446 samplerParams.lodBias, // mipLodBias
447 VK_FALSE, // anisotropyEnable
448 1.0f, // maxAnisotropy
449 VK_FALSE, // compareEnable
450 VK_COMPARE_OP_NEVER, // compareOp
451 samplerParams.minLod, // minLod
452 samplerParams.maxLod, // maxLod
453 samplerParams.borderColor, // borderColor
454 samplerParams.isUnnormalized ? VK_TRUE : VK_FALSE, // unnormalizedCoordinates
457 if (samplerParams.isCompare)
459 samplerCreateInfo.compareEnable = VK_TRUE;
461 DE_FATAL("Not implemented");
464 return samplerCreateInfo;
467 VkImageType mapImageType (ImgDim dim)
474 imType = VK_IMAGE_TYPE_1D;
478 imType = VK_IMAGE_TYPE_2D;
481 imType = VK_IMAGE_TYPE_3D;
484 imType = VK_IMAGE_TYPE_LAST;
491 VkImageViewType mapImageViewType (const ImageViewParameters& imParams)
493 VkImageViewType imViewType;
495 if (imParams.isArrayed)
497 switch (imParams.dim)
500 imViewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
503 imViewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
506 imViewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
509 imViewType = VK_IMAGE_VIEW_TYPE_LAST;
515 switch (imParams.dim)
518 imViewType = VK_IMAGE_VIEW_TYPE_1D;
521 imViewType = VK_IMAGE_VIEW_TYPE_2D;
524 imViewType = VK_IMAGE_VIEW_TYPE_3D;
527 imViewType = VK_IMAGE_VIEW_TYPE_CUBE;
530 imViewType = VK_IMAGE_VIEW_TYPE_LAST;
541 virtual ~DataGenerator (void) {}
543 virtual bool generate (void) = 0;
545 virtual std::vector<ConstPixelBufferAccess> getPba (void) const = 0;
546 virtual std::vector<SampleArguments> getSampleArgs (void) const = 0;
549 DataGenerator (void) {}
552 class TextureFilteringTestInstance : public TestInstance
555 TextureFilteringTestInstance (Context& ctx,
556 const TestCaseData& testCaseData,
557 ShaderExecutor& shaderExecutor,
558 de::MovePtr<DataGenerator> gen)
561 , m_imParams (testCaseData.imParams)
562 , m_samplerParams (testCaseData.samplerParams)
563 , m_sampleLookupSettings (testCaseData.sampleLookupSettings)
564 , m_shaderExecutor (shaderExecutor)
566 , m_vki (m_ctx.getInstanceInterface())
567 , m_vkd (m_ctx.getDeviceInterface())
568 , m_instance (m_ctx.getInstance())
569 , m_physicalDevice (m_ctx.getPhysicalDevice())
570 , m_device (m_ctx.getDevice())
571 , m_uqfi (m_ctx.getUniversalQueueFamilyIndex())
572 , m_pba (testCaseData.pba)
573 , m_gen (gen.release())
575 for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
577 DE_ASSERT(m_imParams.size[compNdx] > 0);
580 m_imExtent.width = m_imParams.size[0];
581 m_imExtent.height = m_imParams.size[1];
582 m_imExtent.depth = m_imParams.size[2];
585 virtual TestStatus iterate (void)
591 TestStatus runTest (void);
592 bool isSupported (void);
593 void createResources (void);
597 tcu::Sampler mapTcuSampler (void);
599 const ImageViewParameters& m_imParams;
600 const SamplerParameters& m_samplerParams;
601 const SampleLookupSettings& m_sampleLookupSettings;
603 std::vector<SampleArguments> m_sampleArguments;
604 deUint32 m_numSamples;
606 ShaderExecutor& m_shaderExecutor;
608 const InstanceInterface& m_vki;
609 const DeviceInterface& m_vkd;
610 VkInstance m_instance;
611 VkPhysicalDevice m_physicalDevice;
615 VkExtent3D m_imExtent;
620 de::MovePtr<Allocation> m_imAllocation;
622 Move<VkImageView> m_imView;
623 Move<VkSampler> m_sampler;
625 std::vector<ConstPixelBufferAccess> m_pba;
626 de::MovePtr<DataGenerator> m_gen;
628 std::vector<Vec4> m_resultSamples;
629 std::vector<Vec4> m_resultCoords;
632 TestStatus TextureFilteringTestInstance::runTest (void)
636 TCU_THROW(NotSupportedError, "Unsupported combination of filtering and image format");
639 TCU_CHECK(m_gen->generate());
640 m_pba = m_gen->getPba();
642 m_sampleArguments = m_gen->getSampleArgs();
643 m_numSamples = (deUint32) m_sampleArguments.size();
646 initializeImage(m_ctx, m_im.get(), &m_pba[0], m_imParams);
648 m_shaderExecutor.addSamplerUniform(0, m_imView.get(), m_sampler.get());
650 deUint64 startTime, endTime;
652 startTime = deGetMicroseconds();
654 endTime = deGetMicroseconds();
656 m_ctx.getTestContext().getLog() << TestLog::Message
657 << "Execution time: "
658 << endTime - startTime
660 << TestLog::EndMessage;
662 startTime = deGetMicroseconds();
663 bool result = verify();
664 endTime = deGetMicroseconds();
666 m_ctx.getTestContext().getLog() << TestLog::Message
667 << "Verification time: "
668 << endTime - startTime
670 << TestLog::EndMessage;
674 return TestStatus::pass("Success");
678 // \todo [2016-06-24 collinbaker] Print report if verification fails
679 return TestStatus::fail("Verification failed");
683 bool TextureFilteringTestInstance::verify (void)
685 // \todo [2016-06-24 collinbaker] Handle cubemaps
687 m_coordBits = (deUint8) m_ctx.getDeviceProperties().limits.subTexelPrecisionBits;
688 m_mipmapBits = (deUint8) m_ctx.getDeviceProperties().limits.mipmapPrecisionBits;
690 SampleVerifier verifier(m_imParams,
692 m_sampleLookupSettings,
697 for (deUint32 sampleNdx = 0; sampleNdx < m_numSamples; ++sampleNdx)
699 if (!verifier.verifySample(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx]))
701 // Re-run with report logging
703 verifier.verifySampleReport(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx], report);
705 m_ctx.getTestContext().getLog()
707 << "Failed verification at sample " << sampleNdx << ".\n"
708 << "\tCoordinate: " << m_sampleArguments[sampleNdx].coord << "\n"
709 << "\tLOD: " << m_sampleArguments[sampleNdx].lod << "\n"
710 << "\tGPU Result: " << m_resultSamples[sampleNdx] << "\n"
711 << TestLog::EndMessage;
713 for (int levelNdx = 0; levelNdx < m_imParams.levels; ++levelNdx)
715 LogImage("", "", m_pba[levelNdx]).write(m_ctx.getTestContext().getLog());
718 m_ctx.getTestContext().getLog()
720 << "Failure report:\n" << report << "\n"
721 << TestLog::EndMessage;
730 void TextureFilteringTestInstance::execute (void)
732 std::vector<float> coords, layers, dRefs, dPdxs, dPdys, lods;
734 for (deUint32 ndx = 0; ndx < m_numSamples; ++ndx)
736 const SampleArguments& sampleArgs = m_sampleArguments[ndx];
738 for (deUint8 compNdx = 0; compNdx < 4; ++compNdx)
740 coords.push_back(sampleArgs.coord[compNdx]);
741 dPdxs .push_back(sampleArgs.dPdx[compNdx]);
742 dPdys .push_back(sampleArgs.dPdy[compNdx]);
745 layers.push_back(sampleArgs.layer);
746 dRefs .push_back(sampleArgs.dRef);
747 lods .push_back(sampleArgs.lod);
750 const void* inputs[6] =
752 reinterpret_cast<const void*>(&coords[0]),
753 reinterpret_cast<const void*>(&layers[0]),
754 reinterpret_cast<const void*>(&dRefs[0]),
755 reinterpret_cast<const void*>(&dPdxs[0]),
756 reinterpret_cast<const void*>(&dPdys[0]),
757 reinterpret_cast<const void*>(&lods[0])
760 // Staging buffers; data will be copied into vectors of Vec4
761 // \todo [2016-06-24 collinbaker] Figure out if I actually need to
762 // use staging buffers
763 std::vector<float> resultSamplesTemp(m_numSamples * 4);
764 std::vector<float> resultCoordsTemp (m_numSamples * 4);
768 reinterpret_cast<void*>(&resultSamplesTemp[0]),
769 reinterpret_cast<void*>(&resultCoordsTemp[0])
772 m_shaderExecutor.execute(m_ctx, m_numSamples, inputs, outputs);
774 m_resultSamples.resize(m_numSamples);
775 m_resultCoords .resize(m_numSamples);
777 for (deUint32 ndx = 0; ndx < m_numSamples; ++ndx)
779 m_resultSamples[ndx] = Vec4(resultSamplesTemp[4 * ndx + 0],
780 resultSamplesTemp[4 * ndx + 1],
781 resultSamplesTemp[4 * ndx + 2],
782 resultSamplesTemp[4 * ndx + 3]);
784 m_resultCoords [ndx] = Vec4(resultCoordsTemp [4 * ndx + 0],
785 resultCoordsTemp [4 * ndx + 1],
786 resultCoordsTemp [4 * ndx + 2],
787 resultCoordsTemp [4 * ndx + 3]);
791 void TextureFilteringTestInstance::createResources (void)
795 const VkImageCreateFlags imCreateFlags =
796 (m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
798 const VkImageCreateInfo imCreateInfo =
800 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
802 imCreateFlags, // flags
803 mapImageType(m_imParams.dim), // imageType
804 m_imParams.format, // format
805 m_imExtent, // extent
806 m_imParams.levels, // mipLevels
807 m_imParams.arrayLayers, // arrayLayers
808 VK_SAMPLE_COUNT_1_BIT, // samples
809 VK_IMAGE_TILING_OPTIMAL, // tiling
810 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, // usage
811 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
812 1, // queueFamilyIndexCount
813 &m_uqfi, // pQueueFamilyIndices
814 VK_IMAGE_LAYOUT_UNDEFINED // initialLayout
817 m_im = createImage(m_vkd, m_device, &imCreateInfo);
819 // Allocate memory for image
821 VkMemoryRequirements imMemReq;
822 m_vkd.getImageMemoryRequirements(m_device, m_im.get(), &imMemReq);
824 m_imAllocation = m_ctx.getDefaultAllocator().allocate(imMemReq, MemoryRequirement::Any);
825 VK_CHECK(m_vkd.bindImageMemory(m_device, m_im.get(), m_imAllocation->getMemory(), m_imAllocation->getOffset()));
827 // Create VkImageView
829 // \todo [2016-06-23 collinbaker] Pick aspectMask based on image type (i.e. support depth and/or stencil images)
830 VkImageSubresourceRange imViewSubresourceRange =
832 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
834 m_imParams.levels, // levelCount
836 m_imParams.arrayLayers // layerCount
839 if (m_imParams.dim == IMG_DIM_CUBE)
841 imViewSubresourceRange.layerCount *= 6;
844 const VkComponentMapping imViewCompMap =
846 VK_COMPONENT_SWIZZLE_R,
847 VK_COMPONENT_SWIZZLE_G,
848 VK_COMPONENT_SWIZZLE_B,
849 VK_COMPONENT_SWIZZLE_A
852 const VkImageViewCreateInfo imViewCreateInfo =
854 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType
858 mapImageViewType(m_imParams), // viewType
859 m_imParams.format, // format
860 imViewCompMap, // components
861 imViewSubresourceRange // subresourceRange
864 m_imView = createImageView(m_vkd, m_device, &imViewCreateInfo);
868 const VkSamplerCreateInfo samplerCreateInfo = mapSamplerCreateInfo(m_samplerParams);
869 m_sampler = createSampler(m_vkd, m_device, &samplerCreateInfo);
872 bool TextureFilteringTestInstance::isSupported (void)
874 const VkImageCreateFlags imCreateFlags =
875 (m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
877 VkImageFormatProperties imFormatProperties;
878 VkFormatProperties formatProperties;
880 m_vki.getPhysicalDeviceImageFormatProperties(m_physicalDevice,
882 mapImageType(m_imParams.dim),
883 VK_IMAGE_TILING_OPTIMAL,
884 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
886 &imFormatProperties);
888 m_vki.getPhysicalDeviceFormatProperties( m_physicalDevice,
892 // \todo [2016-06-23 collinbaker] Check image parameters against imFormatProperties
894 VkFormatFeatureFlags reqImFeatures = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
896 if (m_samplerParams.minFilter == VK_FILTER_LINEAR ||
897 m_samplerParams.magFilter == VK_FILTER_LINEAR ||
898 m_samplerParams.mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
900 reqImFeatures |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
903 return (formatProperties.optimalTilingFeatures & reqImFeatures) == reqImFeatures;
906 class TextureFilteringTestCase : public TestCase
909 TextureFilteringTestCase (tcu::TestContext& testCtx,
911 const char* description)
912 : TestCase(testCtx, name, description)
918 virtual void initPrograms (vk::SourceCollections& programCollection) const
920 DE_ASSERT(m_executor);
921 m_executor->setShaderSources(programCollection);
924 virtual de::MovePtr<DataGenerator> createGenerator (void) const = 0;
926 virtual TestInstance* createInstance (Context& ctx) const
928 return new TextureFilteringTestInstance(ctx, m_testCaseData, *m_executor, createGenerator());
932 de::MovePtr<ShaderExecutor> m_executor;
933 TestCaseData m_testCaseData;
936 void TextureFilteringTestCase::init (void)
938 ShaderSpec shaderSpec;
939 shaderSpec.source = genLookupCode(m_testCaseData.imParams,
940 m_testCaseData.samplerParams,
941 m_testCaseData.sampleLookupSettings);
942 shaderSpec.source += "\nsampledCoord = coord;";
944 shaderSpec.outputs.push_back(Symbol("result", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
945 shaderSpec.outputs.push_back(Symbol("sampledCoord", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
946 shaderSpec.inputs .push_back(Symbol("coord", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
947 shaderSpec.inputs .push_back(Symbol("layer", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
948 shaderSpec.inputs .push_back(Symbol("dRef", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
949 shaderSpec.inputs .push_back(Symbol("dPdx", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
950 shaderSpec.inputs .push_back(Symbol("dPdy", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
951 shaderSpec.inputs .push_back(Symbol("lod", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
953 shaderSpec.globalDeclarations = "layout(set=0, binding=0) uniform highp ";
954 shaderSpec.globalDeclarations += genSamplerDeclaration(m_testCaseData.imParams,
955 m_testCaseData.samplerParams);
956 shaderSpec.globalDeclarations += " testSampler;";
958 m_executor = de::MovePtr<ShaderExecutor>(createExecutor(m_testCaseData.shaderType, shaderSpec));
959 DE_ASSERT(m_executor);
961 m_testCtx.getLog() << *m_executor;
964 class Texture2DGradientTestCase : public TextureFilteringTestCase
967 Texture2DGradientTestCase (TestContext& testCtx,
970 TextureFormat format,
974 VkSamplerMipmapMode mipmapFilter,
975 VkSamplerAddressMode wrappingMode)
977 : TextureFilteringTestCase (testCtx, name, desc)
979 , m_dimensions (dimensions)
980 , m_magFilter (magFilter)
981 , m_minFilter (minFilter)
982 , m_mipmapFilter (mipmapFilter)
983 , m_wrappingMode (wrappingMode)
985 m_testCaseData = genTestCaseData();
992 virtual de::MovePtr<DataGenerator> createGenerator (void) const;
994 TestCaseData genTestCaseData()
998 SampleLookupSettings sampleLookupSettings =
1000 LOOKUP_LOD_MODE_LOD, // lookupLodMode
1001 false, // hasLodBias
1002 false, // isProjective
1005 SamplerParameters samplerParameters =
1007 m_magFilter, // magFilter
1008 m_minFilter, // minFilter
1009 m_mipmapFilter, // mipmapFilter
1010 m_wrappingMode, // wrappingModeU
1011 m_wrappingMode, // wrappingModeV
1012 m_wrappingMode, // wrappingModeW
1013 VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE, // borderColor
1017 false, // isUnnormalized
1021 deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_dimensions[0],
1024 ImageViewParameters imParameters =
1027 mapTextureFormat(m_format), // format
1028 m_dimensions, // size
1029 numLevels, // levels
1036 std::vector<ConstPixelBufferAccess>(),
1039 sampleLookupSettings,
1041 (deUint32) m_args.size(),
1042 glu::SHADERTYPE_FRAGMENT
1049 TextureFormat m_format;
1051 VkFilter m_magFilter;
1052 VkFilter m_minFilter;
1053 VkSamplerMipmapMode m_mipmapFilter;
1054 VkSamplerAddressMode m_wrappingMode;
1056 std::vector<SampleArguments> m_args;
1059 class Texture2DGradientTestCase::Generator : public DataGenerator
1062 Generator (const Texture2DGradientTestCase* testCase) : m_testCase(testCase) {}
1064 virtual ~Generator (void)
1066 delete m_tex.release();
1069 virtual bool generate (void)
1071 m_tex = de::MovePtr<Texture2D>(new Texture2D(m_testCase->m_format,
1072 m_testCase->m_dimensions[0],
1073 m_testCase->m_dimensions[1]));
1075 deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_testCase->m_dimensions[0],
1076 m_testCase->m_dimensions[1])));
1078 TextureFormatInfo fmtInfo = getTextureFormatInfo(m_testCase->m_format);
1080 Vec4 cBias = fmtInfo.valueMin;
1081 Vec4 cScale = fmtInfo.valueMax - fmtInfo.valueMin;
1083 for (deUint8 levelNdx = 0; levelNdx < numLevels; ++levelNdx)
1085 Vec4 gMin = Vec4(0.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
1086 Vec4 gMax = Vec4(1.0f, 1.0f, 1.0f, 0.0f) * cScale + cBias;
1088 m_tex->allocLevel(levelNdx);
1089 fillWithComponentGradients(m_tex->getLevel(levelNdx), gMin, gMax);
1095 virtual std::vector<ConstPixelBufferAccess> getPba (void) const
1097 std::vector<ConstPixelBufferAccess> pba;
1099 const deUint8 numLevels = (deUint8) m_tex->getNumLevels();
1101 for (deUint8 levelNdx = 0; levelNdx < numLevels; ++levelNdx)
1103 pba.push_back(m_tex->getLevel(levelNdx));
1109 virtual std::vector<SampleArguments> getSampleArgs (void) const
1111 std::vector<SampleArguments> args;
1113 const float lodList[] = {-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0};
1115 for (deInt32 i = 0; i < 2 * m_testCase->m_dimensions[0] + 1; ++i)
1117 for (deInt32 j = 0; j < 2 * m_testCase->m_dimensions[1] + 1; ++j)
1119 for (deUint32 lodNdx = 0; lodNdx < DE_LENGTH_OF_ARRAY(lodList); ++lodNdx)
1121 SampleArguments cur;
1122 cur.coord = Vec4((float) i / (float) (2 * m_testCase->m_dimensions[0]),
1123 (float) j / (float) (2 * m_testCase->m_dimensions[1]),
1125 cur.lod = lodList[lodNdx];
1127 args.push_back(cur);
1136 const Texture2DGradientTestCase* m_testCase;
1137 de::MovePtr<Texture2D> m_tex;
1140 de::MovePtr<DataGenerator> Texture2DGradientTestCase::createGenerator (void) const
1142 return de::MovePtr<DataGenerator>(new Generator(this));
1145 TestCaseGroup* create2DFormatTests (TestContext& testCtx)
1147 de::MovePtr<TestCaseGroup> tests(
1148 new TestCaseGroup(testCtx, "formats", "Various image formats"));
1150 VkFormat formats[] =
1152 VK_FORMAT_B4G4R4A4_UNORM_PACK16,
1153 VK_FORMAT_R5G6B5_UNORM_PACK16,
1154 VK_FORMAT_A1R5G5B5_UNORM_PACK16,
1157 VK_FORMAT_R8G8_UNORM,
1158 VK_FORMAT_R8G8_SNORM,
1159 VK_FORMAT_R8G8B8A8_UNORM,
1160 VK_FORMAT_R8G8B8A8_SNORM,
1161 VK_FORMAT_R8G8B8A8_SRGB,
1162 VK_FORMAT_B8G8R8A8_UNORM,
1163 VK_FORMAT_B8G8R8A8_SRGB,
1164 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1165 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
1166 VK_FORMAT_A8B8G8R8_SRGB_PACK32,
1167 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1168 VK_FORMAT_R16_SFLOAT,
1169 VK_FORMAT_R16G16_SFLOAT,
1170 VK_FORMAT_R16G16B16A16_SFLOAT,
1171 VK_FORMAT_B10G11R11_UFLOAT_PACK32,
1172 VK_FORMAT_E5B9G9R9_UFLOAT_PACK32
1175 const IVec3 size(32, 32, 1);
1177 for (deUint32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
1179 std::string prefix = getFormatName(formats[formatNdx]);
1181 Texture2DGradientTestCase* testCaseNearest =
1182 new Texture2DGradientTestCase(
1184 (prefix + "_nearest").c_str(),
1186 mapVkFormat(formats[formatNdx]),
1190 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1191 VK_SAMPLER_ADDRESS_MODE_REPEAT);
1193 tests->addChild(testCaseNearest);
1195 Texture2DGradientTestCase* testCaseLinear =
1196 new Texture2DGradientTestCase(
1198 (prefix + "_linear").c_str(),
1200 mapVkFormat(formats[formatNdx]),
1204 VK_SAMPLER_MIPMAP_MODE_LINEAR,
1205 VK_SAMPLER_ADDRESS_MODE_REPEAT);
1207 tests->addChild(testCaseLinear);
1210 return tests.release();
1213 TestCaseGroup* create2DSizeTests (TestContext& testCtx)
1215 de::MovePtr<TestCaseGroup> tests(
1216 new TestCaseGroup(testCtx, "sizes", "Various size and filtering combinations"));
1218 const VkFilter filters[2] =
1224 const VkSamplerMipmapMode mipmapFilters[2] =
1226 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1227 VK_SAMPLER_MIPMAP_MODE_LINEAR
1230 const VkSamplerAddressMode wrappingModes[2] =
1232 VK_SAMPLER_ADDRESS_MODE_REPEAT,
1233 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE
1250 for (deUint32 sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1252 for (deUint32 magFilterNdx = 0; magFilterNdx < 2; ++magFilterNdx)
1254 for (deUint32 minFilterNdx = 0; minFilterNdx < 2; ++minFilterNdx)
1256 for (deUint32 mipmapFilterNdx = 0; mipmapFilterNdx < 2; ++mipmapFilterNdx)
1258 for (deUint32 wrappingModeNdx = 0; wrappingModeNdx < 2; ++wrappingModeNdx)
1260 std::ostringstream caseName;
1262 caseName << sizes[sizeNdx][0] << "x" << sizes[sizeNdx][1];
1264 switch (filters[magFilterNdx])
1266 case VK_FILTER_NEAREST:
1267 caseName << "_nearest";
1269 case VK_FILTER_LINEAR:
1270 caseName << "_linear";
1276 switch (filters[minFilterNdx])
1278 case VK_FILTER_NEAREST:
1279 caseName << "_nearest";
1281 case VK_FILTER_LINEAR:
1282 caseName << "_linear";
1288 switch (mipmapFilters[mipmapFilterNdx])
1290 case VK_SAMPLER_MIPMAP_MODE_NEAREST:
1291 caseName << "_mipmap_nearest";
1293 case VK_SAMPLER_MIPMAP_MODE_LINEAR:
1294 caseName << "_mipmap_linear";
1300 switch (wrappingModes[wrappingModeNdx])
1302 case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
1303 caseName << "_clamp";
1305 case VK_SAMPLER_ADDRESS_MODE_REPEAT:
1306 caseName << "_repeat";
1312 Texture2DGradientTestCase* testCase =
1313 new Texture2DGradientTestCase(
1315 caseName.str().c_str(),
1317 mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM),
1319 filters[magFilterNdx],
1320 filters[minFilterNdx],
1321 mipmapFilters[mipmapFilterNdx],
1322 wrappingModes[wrappingModeNdx]);
1324 tests->addChild(testCase);
1331 return tests.release();
1334 TestCaseGroup* create2DTests (TestContext& testCtx)
1336 de::MovePtr<TestCaseGroup> tests(
1337 new TestCaseGroup(testCtx, "2d", "2D Image filtering tests"));
1339 tests->addChild(create2DSizeTests(testCtx));
1340 tests->addChild(create2DFormatTests(testCtx));
1342 return tests.release();
1347 TestCaseGroup* createExplicitLodTests (TestContext& testCtx)
1349 de::MovePtr<TestCaseGroup> tests(
1350 new TestCaseGroup(testCtx, "explicit_lod", "Texture filtering with explicit LOD"));
1352 tests->addChild(create2DTests(testCtx));
1354 return tests.release();
1357 } // texture_filtering