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"
41 #include "tcuTexLookupVerifier.hpp"
42 #include "tcuTestLog.hpp"
43 #include "tcuTexture.hpp"
44 #include "tcuTextureUtil.hpp"
45 #include "tcuVector.hpp"
49 #include "deStringUtil.hpp"
50 #include "deUniquePtr.hpp"
68 tcu::FloatFormat getConversionPrecision (VkFormat format)
70 const tcu::FloatFormat reallyLow (0, 0, 8, false, tcu::YES);
71 const tcu::FloatFormat fp16 (-14, 15, 10, false);
72 const tcu::FloatFormat fp32 (-126, 127, 23, true);
76 case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
77 case VK_FORMAT_R5G6B5_UNORM_PACK16:
78 case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
81 case VK_FORMAT_R8_UNORM:
82 case VK_FORMAT_R8_SNORM:
83 case VK_FORMAT_R8G8_UNORM:
84 case VK_FORMAT_R8G8_SNORM:
85 case VK_FORMAT_R8G8B8A8_UNORM:
86 case VK_FORMAT_R8G8B8A8_SNORM:
87 case VK_FORMAT_B8G8R8A8_UNORM:
88 case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
89 case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
90 case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
93 case VK_FORMAT_R16_SFLOAT:
94 case VK_FORMAT_R16G16_SFLOAT:
95 case VK_FORMAT_R16G16B16A16_SFLOAT:
98 case VK_FORMAT_R32_SFLOAT:
99 case VK_FORMAT_R32G32_SFLOAT:
100 case VK_FORMAT_R32G32B32A32_SFLOAT:
104 DE_FATAL("Precision not defined for format");
109 tcu::FloatFormat getFilteringPrecision (VkFormat format)
111 const tcu::FloatFormat reallyLow (0, 0, 6, false, tcu::YES);
112 const tcu::FloatFormat low (0, 0, 7, false, tcu::YES);
113 const tcu::FloatFormat fp16 (-14, 15, 10, false);
114 const tcu::FloatFormat fp32 (-126, 127, 23, true);
118 case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
119 case VK_FORMAT_R5G6B5_UNORM_PACK16:
120 case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
123 case VK_FORMAT_R8_UNORM:
124 case VK_FORMAT_R8_SNORM:
125 case VK_FORMAT_R8G8_UNORM:
126 case VK_FORMAT_R8G8_SNORM:
127 case VK_FORMAT_R8G8B8A8_UNORM:
128 case VK_FORMAT_R8G8B8A8_SNORM:
129 case VK_FORMAT_B8G8R8A8_UNORM:
130 case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
131 case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
132 case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
135 case VK_FORMAT_R16_SFLOAT:
136 case VK_FORMAT_R16G16_SFLOAT:
137 case VK_FORMAT_R16G16B16A16_SFLOAT:
140 case VK_FORMAT_R32_SFLOAT:
141 case VK_FORMAT_R32G32_SFLOAT:
142 case VK_FORMAT_R32G32B32A32_SFLOAT:
146 DE_FATAL("Precision not defined for format");
151 using namespace shaderexecutor;
153 string genSamplerDeclaration(const ImageViewParameters& imParams,
154 const SamplerParameters& samplerParams)
156 string result = "sampler";
158 switch (imParams.dim)
180 if (imParams.isArrayed)
185 if (samplerParams.isCompare)
193 string genLookupCode(const ImageViewParameters& imParams,
194 const SamplerParameters& samplerParams,
195 const SampleLookupSettings& lookupSettings)
199 switch (imParams.dim)
222 DE_ASSERT(dim >= 1 && dim <= 3);
224 int numCoordComp = dim;
226 if (lookupSettings.isProjective)
231 int numArgComp = numCoordComp;
232 bool hasSeparateCompare = false;
234 if (imParams.isArrayed)
236 DE_ASSERT(!lookupSettings.isProjective && "Can't do a projective lookup on an arrayed image!");
241 if (samplerParams.isCompare && numCoordComp == 4)
243 hasSeparateCompare = true;
245 else if (samplerParams.isCompare)
250 // Build coordinate input to texture*() function
253 arg += (char) (numArgComp + '0');
255 arg += (char) (numCoordComp + '0');
258 int numZero = numArgComp - numCoordComp;
260 if (imParams.isArrayed)
266 if (samplerParams.isCompare && !hasSeparateCompare)
272 for (int ndx = 0; ndx < numZero; ++ndx)
279 // Build call to texture*() function
283 code += "result = texture";
285 if (lookupSettings.isProjective)
290 if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
294 else if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_LOD)
299 code += "(testSampler, ";
302 if (samplerParams.isCompare && hasSeparateCompare)
307 if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_DERIVATIVES)
310 code += (char) (numCoordComp + '0');
313 code += (char) (numCoordComp + '0');
316 else if (lookupSettings.lookupLodMode == LOOKUP_LOD_MODE_LOD)
326 void initializeImage(Context& ctx, VkImage im, const ConstPixelBufferAccess* pba, ImageViewParameters imParams)
328 const DeviceInterface& vkd = ctx.getDeviceInterface();
329 const VkDevice dev = ctx.getDevice();
330 const deUint32 uqfi = ctx.getUniversalQueueFamilyIndex();
332 const VkDeviceSize bufSize =
333 getPixelSize(mapVkFormat(imParams.format))
334 * imParams.arrayLayers
340 const VkBufferCreateInfo bufCreateInfo =
342 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
346 VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage
347 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
348 1, // queueFamilyIndexCount
349 &uqfi // pQueueFamilyIndices
352 Unique<VkBuffer> buf(createBuffer(vkd, dev, &bufCreateInfo));
354 VkMemoryRequirements bufMemReq;
355 vkd.getBufferMemoryRequirements(dev, buf.get(), &bufMemReq);
357 de::UniquePtr<Allocation> bufMem(ctx.getDefaultAllocator().allocate(bufMemReq, MemoryRequirement::HostVisible));
358 VK_CHECK(vkd.bindBufferMemory(dev, buf.get(), bufMem->getMemory(), bufMem->getOffset()));
360 const VkCommandPoolCreateInfo copyPoolCreateInfo =
362 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
364 VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,
368 Unique<VkCommandPool> copyPool(createCommandPool(vkd, dev, ©PoolCreateInfo));
370 const VkCommandBufferAllocateInfo copyBufferCreateInfo =
372 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
375 VK_COMMAND_BUFFER_LEVEL_PRIMARY,
379 Unique<VkCommandBuffer> copyBuffer(allocateCommandBuffer(vkd, dev, ©BufferCreateInfo));
381 std::vector<VkBufferImageCopy> copyRegions;
383 deUint8* const bufMapPtr = reinterpret_cast<deUint8*>(bufMem->getHostPtr());
384 deUint8* bufCurPtr = bufMapPtr;
386 for (int level = 0; level < imParams.levels; ++level)
388 const IVec3 curLevelSize = pba[level].getSize();
390 const std::size_t copySize =
391 getPixelSize(mapVkFormat(imParams.format))
392 * curLevelSize[0] * curLevelSize[1] * curLevelSize[2]
393 * imParams.arrayLayers;
395 deMemcpy(bufCurPtr, pba[level].getDataPtr(), copySize);
397 flushMappedMemoryRange(vkd, dev, bufMem->getMemory(), bufMem->getOffset() + (bufCurPtr - bufMapPtr), copySize);
399 const VkImageSubresourceLayers curSubresource =
401 VK_IMAGE_ASPECT_COLOR_BIT,
404 (deUint32)imParams.arrayLayers
407 const VkBufferImageCopy curRegion =
409 (VkDeviceSize) (bufCurPtr - bufMapPtr),
414 {(deUint32)curLevelSize[0], (deUint32)curLevelSize[1], (deUint32)curLevelSize[2]}
417 copyRegions.push_back(curRegion);
419 bufCurPtr += copySize;
422 const VkCommandBufferBeginInfo beginInfo =
424 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
426 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
430 VK_CHECK(vkd.beginCommandBuffer(copyBuffer.get(), &beginInfo));
432 const VkImageSubresourceRange imMemBarSubRange =
434 VK_IMAGE_ASPECT_COLOR_BIT,
436 (deUint32)imParams.levels,
438 (deUint32)imParams.arrayLayers
441 VkImageMemoryBarrier imMemBar =
443 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
446 VK_ACCESS_TRANSFER_WRITE_BIT,
447 VK_IMAGE_LAYOUT_UNDEFINED,
448 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
449 VK_QUEUE_FAMILY_IGNORED,
450 VK_QUEUE_FAMILY_IGNORED,
455 VkBufferMemoryBarrier bufMemBar =
457 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
459 VK_ACCESS_HOST_WRITE_BIT,
460 VK_ACCESS_TRANSFER_READ_BIT,
461 VK_QUEUE_FAMILY_IGNORED,
462 VK_QUEUE_FAMILY_IGNORED,
468 vkd.cmdPipelineBarrier(copyBuffer.get(),
469 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
470 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
479 vkd.cmdCopyBufferToImage(copyBuffer.get(),
482 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
483 (deUint32)copyRegions.size(),
486 imMemBar.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
487 imMemBar.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
488 imMemBar.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
489 imMemBar.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
491 vkd.cmdPipelineBarrier(copyBuffer.get(),
492 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
493 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
502 VK_CHECK(vkd.endCommandBuffer(copyBuffer.get()));
504 const VkSubmitInfo copySubmitInfo =
506 VK_STRUCTURE_TYPE_SUBMIT_INFO,
517 VK_CHECK(vkd.queueSubmit(ctx.getUniversalQueue(), 1, ©SubmitInfo, 0));
518 VK_CHECK(vkd.queueWaitIdle(ctx.getUniversalQueue()));
523 std::vector<ConstPixelBufferAccess> pba;
524 ImageViewParameters imParams;
525 SamplerParameters samplerParams;
526 SampleLookupSettings sampleLookupSettings;
527 glu::ShaderType shaderType;
530 VkSamplerCreateInfo mapSamplerCreateInfo (const SamplerParameters& samplerParams)
532 VkSamplerCreateInfo samplerCreateInfo =
534 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // sType
537 samplerParams.magFilter, // magFilter
538 samplerParams.minFilter, // minFilter
539 samplerParams.mipmapFilter, // mipmapMode
540 samplerParams.wrappingModeU, // addressModeU
541 samplerParams.wrappingModeV, // addressModeV
542 samplerParams.wrappingModeW, // addressMoveW
543 samplerParams.lodBias, // mipLodBias
544 VK_FALSE, // anisotropyEnable
545 1.0f, // maxAnisotropy
546 VK_FALSE, // compareEnable
547 VK_COMPARE_OP_NEVER, // compareOp
548 samplerParams.minLod, // minLod
549 samplerParams.maxLod, // maxLod
550 samplerParams.borderColor, // borderColor
551 samplerParams.isUnnormalized ? VK_TRUE : VK_FALSE, // unnormalizedCoordinates
554 if (samplerParams.isCompare)
556 samplerCreateInfo.compareEnable = VK_TRUE;
558 DE_FATAL("Not implemented");
561 return samplerCreateInfo;
564 VkImageType mapImageType (ImgDim dim)
571 imType = VK_IMAGE_TYPE_1D;
576 imType = VK_IMAGE_TYPE_2D;
580 imType = VK_IMAGE_TYPE_3D;
584 imType = VK_IMAGE_TYPE_LAST;
591 VkImageViewType mapImageViewType (const ImageViewParameters& imParams)
593 VkImageViewType imViewType;
595 if (imParams.isArrayed)
597 switch (imParams.dim)
600 imViewType = VK_IMAGE_VIEW_TYPE_1D_ARRAY;
604 imViewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
608 imViewType = VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
612 imViewType = VK_IMAGE_VIEW_TYPE_LAST;
618 switch (imParams.dim)
621 imViewType = VK_IMAGE_VIEW_TYPE_1D;
625 imViewType = VK_IMAGE_VIEW_TYPE_2D;
629 imViewType = VK_IMAGE_VIEW_TYPE_3D;
633 imViewType = VK_IMAGE_VIEW_TYPE_CUBE;
637 imViewType = VK_IMAGE_VIEW_TYPE_LAST;
648 virtual ~DataGenerator (void) {}
650 virtual bool generate (void) = 0;
652 virtual std::vector<ConstPixelBufferAccess> getPba (void) const = 0;
653 virtual std::vector<SampleArguments> getSampleArgs (void) const = 0;
656 DataGenerator (void) {}
659 class TextureFilteringTestInstance : public TestInstance
662 TextureFilteringTestInstance (Context& ctx,
663 const TestCaseData& testCaseData,
664 ShaderExecutor& shaderExecutor,
665 de::MovePtr<DataGenerator> gen);
667 virtual TestStatus iterate (void) { return runTest(); }
670 TestStatus runTest (void);
671 bool isSupported (void);
672 void createResources (void);
676 tcu::Sampler mapTcuSampler (void) const;
678 const ImageViewParameters m_imParams;
679 const SamplerParameters m_samplerParams;
680 const SampleLookupSettings m_sampleLookupSettings;
682 std::vector<SampleArguments> m_sampleArguments;
683 deUint32 m_numSamples;
685 ShaderExecutor& m_shaderExecutor;
687 de::MovePtr<Allocation> m_imAllocation;
689 Move<VkImageView> m_imView;
690 Move<VkSampler> m_sampler;
692 std::vector<ConstPixelBufferAccess> m_levels;
693 de::MovePtr<DataGenerator> m_gen;
695 std::vector<Vec4> m_resultSamples;
696 std::vector<Vec4> m_resultCoords;
699 TextureFilteringTestInstance::TextureFilteringTestInstance (Context& ctx,
700 const TestCaseData& testCaseData,
701 ShaderExecutor& shaderExecutor,
702 de::MovePtr<DataGenerator> gen)
704 , m_imParams (testCaseData.imParams)
705 , m_samplerParams (testCaseData.samplerParams)
706 , m_sampleLookupSettings (testCaseData.sampleLookupSettings)
707 , m_shaderExecutor (shaderExecutor)
708 , m_levels (testCaseData.pba)
709 , m_gen (gen.release())
711 for (deUint8 compNdx = 0; compNdx < 3; ++compNdx)
712 DE_ASSERT(m_imParams.size[compNdx] > 0);
715 TestStatus TextureFilteringTestInstance::runTest (void)
718 TCU_THROW(NotSupportedError, "Unsupported combination of filtering and image format");
720 TCU_CHECK(m_gen->generate());
721 m_levels = m_gen->getPba();
723 m_sampleArguments = m_gen->getSampleArgs();
724 m_numSamples = (deUint32)m_sampleArguments.size();
727 initializeImage(m_context, m_im.get(), &m_levels[0], m_imParams);
729 m_shaderExecutor.addSamplerUniform(0, m_imView.get(), m_sampler.get());
731 deUint64 startTime, endTime;
733 startTime = deGetMicroseconds();
735 endTime = deGetMicroseconds();
737 m_context.getTestContext().getLog() << TestLog::Message
738 << "Execution time: "
739 << endTime - startTime
741 << TestLog::EndMessage;
743 startTime = deGetMicroseconds();
744 bool result = verify();
745 endTime = deGetMicroseconds();
747 m_context.getTestContext().getLog() << TestLog::Message
748 << "Verification time: "
749 << endTime - startTime
751 << TestLog::EndMessage;
755 return TestStatus::pass("Success");
759 // \todo [2016-06-24 collinbaker] Print report if verification fails
760 return TestStatus::fail("Verification failed");
764 bool TextureFilteringTestInstance::verify (void)
766 // \todo [2016-06-24 collinbaker] Handle cubemaps
768 const int coordBits = (int)m_context.getDeviceProperties().limits.subTexelPrecisionBits;
769 const int mipmapBits = (int)m_context.getDeviceProperties().limits.mipmapPrecisionBits;
770 const int maxPrintedFailures = 5;
773 const SampleVerifier verifier (m_imParams,
775 m_sampleLookupSettings,
778 getConversionPrecision(m_imParams.format),
779 getFilteringPrecision(m_imParams.format),
783 for (deUint32 sampleNdx = 0; sampleNdx < m_numSamples; ++sampleNdx)
785 if (!verifier.verifySample(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx]))
787 if (failCount++ < maxPrintedFailures)
789 // Re-run with report logging
791 verifier.verifySampleReport(m_sampleArguments[sampleNdx], m_resultSamples[sampleNdx], report);
793 m_context.getTestContext().getLog()
794 << TestLog::Section("Failed sample", "Failed sample")
796 << "Sample " << sampleNdx << ".\n"
797 << "\tCoordinate: " << m_sampleArguments[sampleNdx].coord << "\n"
798 << "\tLOD: " << m_sampleArguments[sampleNdx].lod << "\n"
799 << "\tGPU Result: " << m_resultSamples[sampleNdx] << "\n\n"
800 << "Failure report:\n" << report << "\n"
801 << TestLog::EndMessage
802 << TestLog::EndSection;
807 m_context.getTestContext().getLog()
809 << "Passed " << m_numSamples - failCount << " out of " << m_numSamples << "."
810 << TestLog::EndMessage;
812 return failCount == 0;
815 void TextureFilteringTestInstance::execute (void)
817 std::vector<float> coords, layers, dRefs, dPdxs, dPdys, lods;
819 for (deUint32 ndx = 0; ndx < m_numSamples; ++ndx)
821 const SampleArguments& sampleArgs = m_sampleArguments[ndx];
823 for (deUint8 compNdx = 0; compNdx < 4; ++compNdx)
825 coords.push_back(sampleArgs.coord[compNdx]);
826 dPdxs .push_back(sampleArgs.dPdx[compNdx]);
827 dPdys .push_back(sampleArgs.dPdy[compNdx]);
830 layers.push_back(sampleArgs.layer);
831 dRefs .push_back(sampleArgs.dRef);
832 lods .push_back(sampleArgs.lod);
835 const void* inputs[6] =
837 reinterpret_cast<const void*>(&coords[0]),
838 reinterpret_cast<const void*>(&layers[0]),
839 reinterpret_cast<const void*>(&dRefs[0]),
840 reinterpret_cast<const void*>(&dPdxs[0]),
841 reinterpret_cast<const void*>(&dPdys[0]),
842 reinterpret_cast<const void*>(&lods[0])
845 // Staging buffers; data will be copied into vectors of Vec4
846 // \todo [2016-06-24 collinbaker] Figure out if I actually need to
847 // use staging buffers
848 std::vector<float> resultSamplesTemp(m_numSamples * 4);
849 std::vector<float> resultCoordsTemp (m_numSamples * 4);
853 reinterpret_cast<void*>(&resultSamplesTemp[0]),
854 reinterpret_cast<void*>(&resultCoordsTemp[0])
857 m_shaderExecutor.execute(m_context, m_numSamples, inputs, outputs);
859 m_resultSamples.resize(m_numSamples);
860 m_resultCoords .resize(m_numSamples);
862 for (deUint32 ndx = 0; ndx < m_numSamples; ++ndx)
864 m_resultSamples[ndx] = Vec4(resultSamplesTemp[4 * ndx + 0],
865 resultSamplesTemp[4 * ndx + 1],
866 resultSamplesTemp[4 * ndx + 2],
867 resultSamplesTemp[4 * ndx + 3]);
869 m_resultCoords [ndx] = Vec4(resultCoordsTemp [4 * ndx + 0],
870 resultCoordsTemp [4 * ndx + 1],
871 resultCoordsTemp [4 * ndx + 2],
872 resultCoordsTemp [4 * ndx + 3]);
876 void TextureFilteringTestInstance::createResources (void)
880 const DeviceInterface& vkd = m_context.getDeviceInterface();
881 const VkDevice device = m_context.getDevice();
883 const deUint32 queueFamily = m_context.getUniversalQueueFamilyIndex();
884 const VkImageCreateFlags imCreateFlags =(m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
886 const VkImageCreateInfo imCreateInfo =
888 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
891 mapImageType(m_imParams.dim),
893 makeExtent3D(m_imParams.size[0], m_imParams.size[1], m_imParams.size[2]),
894 (deUint32)m_imParams.levels,
895 (deUint32)m_imParams.arrayLayers,
896 VK_SAMPLE_COUNT_1_BIT,
897 VK_IMAGE_TILING_OPTIMAL,
898 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
899 VK_SHARING_MODE_EXCLUSIVE,
902 VK_IMAGE_LAYOUT_UNDEFINED
905 m_im = createImage(vkd, device, &imCreateInfo);
907 // Allocate memory for image
909 VkMemoryRequirements imMemReq;
910 vkd.getImageMemoryRequirements(device, m_im.get(), &imMemReq);
912 m_imAllocation = m_context.getDefaultAllocator().allocate(imMemReq, MemoryRequirement::Any);
913 VK_CHECK(vkd.bindImageMemory(device, m_im.get(), m_imAllocation->getMemory(), m_imAllocation->getOffset()));
915 // Create VkImageView
917 // \todo [2016-06-23 collinbaker] Pick aspectMask based on image type (i.e. support depth and/or stencil images)
918 DE_ASSERT(m_imParams.dim != IMG_DIM_CUBE); // \todo Support cube maps
919 const VkImageSubresourceRange imViewSubresourceRange =
921 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
923 (deUint32)m_imParams.levels, // levelCount
925 (deUint32)m_imParams.arrayLayers // layerCount
928 const VkComponentMapping imViewCompMap =
930 VK_COMPONENT_SWIZZLE_R,
931 VK_COMPONENT_SWIZZLE_G,
932 VK_COMPONENT_SWIZZLE_B,
933 VK_COMPONENT_SWIZZLE_A
936 const VkImageViewCreateInfo imViewCreateInfo =
938 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType
942 mapImageViewType(m_imParams), // viewType
943 m_imParams.format, // format
944 imViewCompMap, // components
945 imViewSubresourceRange // subresourceRange
948 m_imView = createImageView(vkd, device, &imViewCreateInfo);
952 const VkSamplerCreateInfo samplerCreateInfo = mapSamplerCreateInfo(m_samplerParams);
953 m_sampler = createSampler(vkd, device, &samplerCreateInfo);
956 VkFormatFeatureFlags getRequiredFormatFeatures (const SamplerParameters& samplerParams)
958 VkFormatFeatureFlags features = VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
960 if (samplerParams.minFilter == VK_FILTER_LINEAR ||
961 samplerParams.magFilter == VK_FILTER_LINEAR ||
962 samplerParams.mipmapFilter == VK_SAMPLER_MIPMAP_MODE_LINEAR)
964 features |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
970 bool TextureFilteringTestInstance::isSupported (void)
972 const VkImageCreateFlags imCreateFlags = (m_imParams.dim == IMG_DIM_CUBE) ? VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0;
973 const VkFormatFeatureFlags reqImFeatures = getRequiredFormatFeatures(m_samplerParams);
975 const VkImageFormatProperties imFormatProperties = getPhysicalDeviceImageFormatProperties(m_context.getInstanceInterface(),
976 m_context.getPhysicalDevice(),
978 mapImageType(m_imParams.dim),
979 VK_IMAGE_TILING_OPTIMAL,
980 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
982 const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(m_context.getInstanceInterface(),
983 m_context.getPhysicalDevice(),
986 // \todo [2016-06-23 collinbaker] Check image parameters against imFormatProperties
987 DE_UNREF(imFormatProperties);
989 return (formatProperties.optimalTilingFeatures & reqImFeatures) == reqImFeatures;
992 class TextureFilteringTestCase : public TestCase
995 TextureFilteringTestCase (tcu::TestContext& testCtx,
997 const char* description)
998 : TestCase(testCtx, name, description)
1004 virtual void initPrograms (vk::SourceCollections& programCollection) const
1006 DE_ASSERT(m_executor);
1007 m_executor->setShaderSources(programCollection);
1010 virtual de::MovePtr<DataGenerator> createGenerator (void) const = 0;
1012 virtual TestInstance* createInstance (Context& ctx) const
1014 return new TextureFilteringTestInstance(ctx, m_testCaseData, *m_executor, createGenerator());
1018 de::MovePtr<ShaderExecutor> m_executor;
1019 TestCaseData m_testCaseData;
1022 void TextureFilteringTestCase::init (void)
1024 ShaderSpec shaderSpec;
1025 shaderSpec.source = genLookupCode(m_testCaseData.imParams,
1026 m_testCaseData.samplerParams,
1027 m_testCaseData.sampleLookupSettings);
1028 shaderSpec.source += "\nsampledCoord = coord;";
1030 shaderSpec.outputs.push_back(Symbol("result", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
1031 shaderSpec.outputs.push_back(Symbol("sampledCoord", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
1032 shaderSpec.inputs .push_back(Symbol("coord", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
1033 shaderSpec.inputs .push_back(Symbol("layer", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
1034 shaderSpec.inputs .push_back(Symbol("dRef", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
1035 shaderSpec.inputs .push_back(Symbol("dPdx", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
1036 shaderSpec.inputs .push_back(Symbol("dPdy", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
1037 shaderSpec.inputs .push_back(Symbol("lod", glu::VarType(glu::TYPE_FLOAT, glu::PRECISION_HIGHP)));
1039 shaderSpec.globalDeclarations = "layout(set=0, binding=0) uniform highp ";
1040 shaderSpec.globalDeclarations += genSamplerDeclaration(m_testCaseData.imParams,
1041 m_testCaseData.samplerParams);
1042 shaderSpec.globalDeclarations += " testSampler;";
1044 m_executor = de::MovePtr<ShaderExecutor>(createExecutor(m_testCaseData.shaderType, shaderSpec));
1045 DE_ASSERT(m_executor);
1047 m_testCtx.getLog() << *m_executor;
1050 class Texture2DGradientTestCase : public TextureFilteringTestCase
1053 Texture2DGradientTestCase (TestContext& testCtx,
1056 TextureFormat format,
1060 VkSamplerMipmapMode mipmapFilter,
1061 VkSamplerAddressMode wrappingMode,
1062 bool useDerivatives)
1064 : TextureFilteringTestCase (testCtx, name, desc)
1066 , m_dimensions (dimensions)
1067 , m_magFilter (magFilter)
1068 , m_minFilter (minFilter)
1069 , m_mipmapFilter (mipmapFilter)
1070 , m_wrappingMode (wrappingMode)
1071 , m_useDerivatives (useDerivatives)
1073 m_testCaseData = genTestCaseData();
1080 virtual de::MovePtr<DataGenerator> createGenerator (void) const;
1082 TestCaseData genTestCaseData()
1086 const SampleLookupSettings sampleLookupSettings =
1088 m_useDerivatives ? LOOKUP_LOD_MODE_DERIVATIVES : LOOKUP_LOD_MODE_LOD, // lookupLodMode
1089 false, // hasLodBias
1090 false, // isProjective
1093 const SamplerParameters samplerParameters =
1101 VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE,
1109 const deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_dimensions[0],
1112 const ImageViewParameters imParameters =
1115 mapTextureFormat(m_format),
1122 const TestCaseData data =
1124 std::vector<ConstPixelBufferAccess>(),
1127 sampleLookupSettings,
1128 glu::SHADERTYPE_FRAGMENT
1135 const TextureFormat m_format;
1136 const IVec3 m_dimensions;
1137 const VkFilter m_magFilter;
1138 const VkFilter m_minFilter;
1139 const VkSamplerMipmapMode m_mipmapFilter;
1140 const VkSamplerAddressMode m_wrappingMode;
1141 const bool m_useDerivatives;
1144 class Texture2DGradientTestCase::Generator : public DataGenerator
1147 Generator (const Texture2DGradientTestCase* testCase) : m_testCase(testCase) {}
1149 virtual ~Generator (void)
1151 delete m_tex.release();
1154 virtual bool generate (void)
1156 m_tex = de::MovePtr<Texture2D>(new Texture2D(m_testCase->m_format,
1157 m_testCase->m_dimensions[0],
1158 m_testCase->m_dimensions[1]));
1160 const deUint8 numLevels = (deUint8) (1 + deLog2Floor32(de::max(m_testCase->m_dimensions[0],
1161 m_testCase->m_dimensions[1])));
1163 const TextureFormatInfo fmtInfo = getTextureFormatInfo(m_testCase->m_format);
1165 const Vec4 cBias = fmtInfo.valueMin;
1166 const Vec4 cScale = fmtInfo.valueMax - fmtInfo.valueMin;
1168 for (deUint8 levelNdx = 0; levelNdx < numLevels; ++levelNdx)
1170 const Vec4 gMin = Vec4(0.0f, 0.0f, 0.0f, 1.0f) * cScale + cBias;
1171 const Vec4 gMax = Vec4(1.0f, 1.0f, 1.0f, 0.0f) * cScale + cBias;
1173 m_tex->allocLevel(levelNdx);
1174 fillWithComponentGradients(m_tex->getLevel(levelNdx), gMin, gMax);
1180 virtual std::vector<ConstPixelBufferAccess> getPba (void) const
1182 std::vector<ConstPixelBufferAccess> pba;
1184 const deUint8 numLevels = (deUint8) m_tex->getNumLevels();
1186 for (deUint8 levelNdx = 0; levelNdx < numLevels; ++levelNdx)
1188 pba.push_back(m_tex->getLevel(levelNdx));
1194 virtual std::vector<SampleArguments> getSampleArgs (void) const
1196 std::vector<SampleArguments> args;
1198 if (m_testCase->m_useDerivatives)
1207 {Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(0.0f, 0.0f, 0.0f, 0.0f)},
1208 {Vec4(1.0f, 1.0f, 1.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f)},
1209 {Vec4(0.0f, 0.0f, 0.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f)},
1210 {Vec4(1.0f, 1.0f, 1.0f, 0.0f), Vec4(0.0f, 0.0f, 0.0f, 0.0f)},
1211 {Vec4(2.0f, 2.0f, 2.0f, 0.0f), Vec4(2.0f, 2.0f, 2.0f, 0.0f)}
1214 for (deInt32 i = 0; i < 2 * m_testCase->m_dimensions[0] + 1; ++i)
1216 for (deInt32 j = 0; j < 2 * m_testCase->m_dimensions[1] + 1; ++j)
1218 for (deUint32 derivNdx = 0; derivNdx < DE_LENGTH_OF_ARRAY(derivativePairs); ++derivNdx)
1220 SampleArguments cur;
1221 cur.coord = Vec4((float)i / (float)(2 * m_testCase->m_dimensions[0]),
1222 (float)j / (float)(2 * m_testCase->m_dimensions[1]),
1224 cur.dPdx = derivativePairs[derivNdx].dPdx;
1225 cur.dPdy = derivativePairs[derivNdx].dPdy;
1227 args.push_back(cur);
1234 const float lodList[] = {-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0};
1236 for (deInt32 i = 0; i < 2 * m_testCase->m_dimensions[0] + 1; ++i)
1238 for (deInt32 j = 0; j < 2 * m_testCase->m_dimensions[1] + 1; ++j)
1240 for (deUint32 lodNdx = 0; lodNdx < DE_LENGTH_OF_ARRAY(lodList); ++lodNdx)
1242 SampleArguments cur;
1243 cur.coord = Vec4((float)i / (float)(2 * m_testCase->m_dimensions[0]),
1244 (float)j / (float)(2 * m_testCase->m_dimensions[1]),
1246 cur.lod = lodList[lodNdx];
1248 args.push_back(cur);
1258 const Texture2DGradientTestCase* m_testCase;
1259 de::MovePtr<Texture2D> m_tex;
1262 de::MovePtr<DataGenerator> Texture2DGradientTestCase::createGenerator (void) const
1264 return de::MovePtr<DataGenerator>(new Generator(this));
1267 TestCaseGroup* create2DFormatTests (TestContext& testCtx)
1269 de::MovePtr<TestCaseGroup> tests(
1270 new TestCaseGroup(testCtx, "formats", "Various image formats"));
1272 const VkFormat formats[] =
1274 VK_FORMAT_B4G4R4A4_UNORM_PACK16,
1275 VK_FORMAT_R5G6B5_UNORM_PACK16,
1276 VK_FORMAT_A1R5G5B5_UNORM_PACK16,
1279 VK_FORMAT_R8G8_UNORM,
1280 VK_FORMAT_R8G8_SNORM,
1281 VK_FORMAT_R8G8B8A8_UNORM,
1282 VK_FORMAT_R8G8B8A8_SNORM,
1283 // VK_FORMAT_R8G8B8A8_SRGB,
1284 VK_FORMAT_B8G8R8A8_UNORM,
1285 // VK_FORMAT_B8G8R8A8_SRGB,
1286 VK_FORMAT_A8B8G8R8_UNORM_PACK32,
1287 VK_FORMAT_A8B8G8R8_SNORM_PACK32,
1288 // VK_FORMAT_A8B8G8R8_SRGB_PACK32,
1289 VK_FORMAT_A2B10G10R10_UNORM_PACK32,
1290 VK_FORMAT_R16_SFLOAT,
1291 VK_FORMAT_R16G16_SFLOAT,
1292 VK_FORMAT_R16G16B16A16_SFLOAT,
1293 VK_FORMAT_R32_SFLOAT,
1294 VK_FORMAT_R32G32_SFLOAT,
1295 VK_FORMAT_R32G32B32A32_SFLOAT,
1296 // VK_FORMAT_B10G11R11_UFLOAT_PACK32,
1297 // VK_FORMAT_E5B9G9R9_UFLOAT_PACK32
1300 const IVec3 size(32, 32, 1);
1302 for (deUint32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx)
1304 const std::string prefix = de::toLower(std::string(getFormatName(formats[formatNdx])).substr(10));
1306 Texture2DGradientTestCase* testCaseNearest =
1307 new Texture2DGradientTestCase(
1309 (prefix + "_nearest").c_str(),
1311 mapVkFormat(formats[formatNdx]),
1315 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1316 VK_SAMPLER_ADDRESS_MODE_REPEAT,
1319 tests->addChild(testCaseNearest);
1321 Texture2DGradientTestCase* testCaseLinear =
1322 new Texture2DGradientTestCase(
1324 (prefix + "_linear").c_str(),
1326 mapVkFormat(formats[formatNdx]),
1330 VK_SAMPLER_MIPMAP_MODE_LINEAR,
1331 VK_SAMPLER_ADDRESS_MODE_REPEAT,
1334 tests->addChild(testCaseLinear);
1337 return tests.release();
1340 TestCaseGroup* create2DDerivTests (TestContext& testCtx)
1342 de::MovePtr<TestCaseGroup> tests(
1343 new TestCaseGroup(testCtx, "derivatives", "Explicit derivative tests"));
1345 const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1346 const VkSamplerAddressMode wrappingMode = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
1347 const IVec3 size = IVec3(16, 16, 1);
1349 const VkFilter filters[2] =
1355 const VkSamplerMipmapMode mipmapFilters[2] =
1357 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1358 VK_SAMPLER_MIPMAP_MODE_LINEAR,
1361 for (int magFilterNdx = 0; magFilterNdx < DE_LENGTH_OF_ARRAY(filters); ++magFilterNdx)
1363 for (int minFilterNdx = 0; minFilterNdx < DE_LENGTH_OF_ARRAY(filters); ++minFilterNdx)
1365 for (int mipmapFilterNdx = 0; mipmapFilterNdx < DE_LENGTH_OF_ARRAY(mipmapFilters); ++mipmapFilterNdx)
1367 std::ostringstream caseName;
1369 switch (filters[magFilterNdx])
1371 case VK_FILTER_NEAREST:
1372 caseName << "nearest";
1375 case VK_FILTER_LINEAR:
1376 caseName << "linear";
1383 switch (filters[minFilterNdx])
1385 case VK_FILTER_NEAREST:
1386 caseName << "_nearest";
1389 case VK_FILTER_LINEAR:
1390 caseName << "_linear";
1397 caseName << "_mipmap";
1399 switch (mipmapFilters[mipmapFilterNdx])
1401 case VK_SAMPLER_MIPMAP_MODE_NEAREST:
1402 caseName << "_nearest";
1405 case VK_SAMPLER_MIPMAP_MODE_LINEAR:
1406 caseName << "_linear";
1413 Texture2DGradientTestCase* testCase =
1414 new Texture2DGradientTestCase(
1416 caseName.str().c_str(),
1418 mapVkFormat(format),
1420 filters[magFilterNdx],
1421 filters[minFilterNdx],
1422 mipmapFilters[mipmapFilterNdx],
1426 tests->addChild(testCase);
1431 return tests.release();
1434 TestCaseGroup* create2DSizeTests (TestContext& testCtx)
1436 de::MovePtr<TestCaseGroup> tests(
1437 new TestCaseGroup(testCtx, "sizes", "Various size and filtering combinations"));
1439 const VkFilter filters[2] =
1445 const VkSamplerMipmapMode mipmapFilters[2] =
1447 VK_SAMPLER_MIPMAP_MODE_NEAREST,
1448 VK_SAMPLER_MIPMAP_MODE_LINEAR
1451 const VkSamplerAddressMode wrappingModes[2] =
1453 VK_SAMPLER_ADDRESS_MODE_REPEAT,
1454 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE
1457 const IVec3 sizes[] =
1471 for (deUint32 sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes); ++sizeNdx)
1473 for (deUint32 magFilterNdx = 0; magFilterNdx < 2; ++magFilterNdx)
1475 for (deUint32 minFilterNdx = 0; minFilterNdx < 2; ++minFilterNdx)
1477 for (deUint32 mipmapFilterNdx = 0; mipmapFilterNdx < 2; ++mipmapFilterNdx)
1479 for (deUint32 wrappingModeNdx = 0; wrappingModeNdx < 2; ++wrappingModeNdx)
1481 std::ostringstream caseName;
1483 caseName << sizes[sizeNdx][0] << "x" << sizes[sizeNdx][1];
1485 switch (filters[magFilterNdx])
1487 case VK_FILTER_NEAREST:
1488 caseName << "_nearest";
1491 case VK_FILTER_LINEAR:
1492 caseName << "_linear";
1499 switch (filters[minFilterNdx])
1501 case VK_FILTER_NEAREST:
1502 caseName << "_nearest";
1505 case VK_FILTER_LINEAR:
1506 caseName << "_linear";
1513 switch (mipmapFilters[mipmapFilterNdx])
1515 case VK_SAMPLER_MIPMAP_MODE_NEAREST:
1516 caseName << "_mipmap_nearest";
1519 case VK_SAMPLER_MIPMAP_MODE_LINEAR:
1520 caseName << "_mipmap_linear";
1527 switch (wrappingModes[wrappingModeNdx])
1529 case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE:
1530 caseName << "_clamp";
1533 case VK_SAMPLER_ADDRESS_MODE_REPEAT:
1534 caseName << "_repeat";
1541 Texture2DGradientTestCase* testCase =
1542 new Texture2DGradientTestCase(
1544 caseName.str().c_str(),
1546 mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM),
1548 filters[magFilterNdx],
1549 filters[minFilterNdx],
1550 mipmapFilters[mipmapFilterNdx],
1551 wrappingModes[wrappingModeNdx],
1554 tests->addChild(testCase);
1561 return tests.release();
1564 TestCaseGroup* create2DTests (TestContext& testCtx)
1566 de::MovePtr<TestCaseGroup> tests(
1567 new TestCaseGroup(testCtx, "2d", "2D Image filtering tests"));
1569 tests->addChild(create2DSizeTests(testCtx));
1570 tests->addChild(create2DFormatTests(testCtx));
1571 tests->addChild(create2DDerivTests(testCtx));
1573 return tests.release();
1578 TestCaseGroup* createExplicitLodTests (TestContext& testCtx)
1580 de::MovePtr<TestCaseGroup> tests(
1581 new TestCaseGroup(testCtx, "explicit_lod", "Texture filtering with explicit LOD"));
1583 tests->addChild(create2DTests(testCtx));
1585 return tests.release();