| /*------------------------------------------------------------------------ |
| * Vulkan Conformance Tests |
| * ------------------------ |
| * |
| * Copyright (c) 2019 The Khronos Group Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| *//*! |
| * \file vktImageAstcDecodeModeTests.cpp |
| * \brief Astc decode mode tests |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "vktImageAstcDecodeModeTests.hpp" |
| #include "vktImageLoadStoreUtil.hpp" |
| |
| #include "vktTestCaseUtil.hpp" |
| #include "vkBarrierUtil.hpp" |
| #include "vkBuilderUtil.hpp" |
| #include "vkQueryUtil.hpp" |
| #include "vkCmdUtil.hpp" |
| #include "vkObjUtil.hpp" |
| |
| #include "tcuAstcUtil.hpp" |
| #include "tcuTextureUtil.hpp" |
| #include "tcuTexture.hpp" |
| #include "tcuCompressedTexture.hpp" |
| #include "tcuImageCompare.hpp" |
| |
| #include "deRandom.hpp" |
| #include <vector> |
| |
| using namespace vk; |
| namespace vkt |
| { |
| namespace image |
| { |
| namespace |
| { |
| using std::string; |
| using std::vector; |
| using tcu::TestContext; |
| using tcu::TestStatus; |
| using tcu::UVec3; |
| using tcu::IVec3; |
| using tcu::CompressedTexFormat; |
| using tcu::CompressedTexture; |
| using de::MovePtr; |
| using de::SharedPtr; |
| using de::Random; |
| |
| struct TestParameters |
| { |
| ImageType imageType; |
| UVec3 imageSize; |
| |
| VkFormat testedFormat; |
| deBool testedIsUnorm; |
| VkFormat testedDecodeMode; |
| VkImageUsageFlags testedImageUsage; |
| |
| VkFormat resultFormat; |
| VkImageUsageFlags resultImageUsage; |
| }; |
| |
| class BasicComputeTestInstance : public TestInstance |
| { |
| public: |
| BasicComputeTestInstance (Context& context, |
| const TestParameters& parameters); |
| |
| TestStatus iterate (void); |
| |
| protected: |
| |
| const TestParameters m_parameters; |
| }; |
| |
| BasicComputeTestInstance::BasicComputeTestInstance (Context& context, const TestParameters& parameters) |
| : TestInstance (context) |
| , m_parameters (parameters) |
| { |
| } |
| |
| TestStatus BasicComputeTestInstance::iterate (void) |
| { |
| Allocator& allocator = m_context.getDefaultAllocator(); |
| const DeviceInterface& vk = m_context.getDeviceInterface(); |
| const VkDevice device = m_context.getDevice(); |
| const VkQueue queue = m_context.getUniversalQueue(); |
| const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); |
| const VkImageType imageType = mapImageType(m_parameters.imageType); |
| const VkExtent3D extentCompressed = makeExtent3D(getCompressedImageResolutionInBlocks(m_parameters.testedFormat, m_parameters.imageSize)); |
| const VkExtent3D extentUnCompressed = makeExtent3D(m_parameters.imageSize); |
| const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); |
| const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); |
| const Unique<VkShaderModule> shaderModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0)); |
| |
| const VkImageCreateInfo compressedImageInfo = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | |
| VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT, // VkImageCreateFlags flags; |
| imageType, // VkImageType imageType; |
| m_parameters.testedFormat, // VkFormat format; |
| extentCompressed, // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| 1u, // deUint32 arrayLayers; |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_SAMPLED_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 0u, // deUint32 queueFamilyIndexCount; |
| DE_NULL, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| const VkImageCreateInfo resultImageInfo = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; |
| DE_NULL, // const void* pNext; |
| 0u, // VkImageCreateFlags flags; |
| imageType, // VkImageType imageType; |
| m_parameters.resultFormat, // VkFormat format; |
| extentUnCompressed, // VkExtent3D extent; |
| 1u, // deUint32 mipLevels; |
| 1u, // deUint32 arrayLayers; |
| VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; |
| VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; |
| VK_IMAGE_USAGE_SAMPLED_BIT | |
| VK_IMAGE_USAGE_STORAGE_BIT | |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage; |
| VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; |
| 0u, // deUint32 queueFamilyIndexCount; |
| DE_NULL, // const deUint32* pQueueFamilyIndices; |
| VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; |
| }; |
| |
| // create images |
| Image testedImage (vk, device, allocator, compressedImageInfo, MemoryRequirement::Any); |
| Image referenceImage (vk, device, allocator, compressedImageInfo, MemoryRequirement::Any); |
| Image resultImage (vk, device, allocator, resultImageInfo, MemoryRequirement::Any); |
| |
| // create image views |
| const VkImageViewType imageViewType (mapImageViewType(m_parameters.imageType)); |
| VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); |
| |
| VkImageViewASTCDecodeModeEXT decodeMode = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT, |
| DE_NULL, |
| m_parameters.testedDecodeMode |
| }; |
| |
| const VkImageViewCreateInfo imageViewParams = |
| { |
| VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; |
| &decodeMode, // const void* pNext; |
| 0u, // VkImageViewCreateFlags flags; |
| testedImage.get(), // VkImage image; |
| imageViewType, // VkImageViewType viewType; |
| m_parameters.testedFormat, // VkFormat format; |
| makeComponentMappingRGBA(), // VkComponentMapping components; |
| subresourceRange, // VkImageSubresourceRange subresourceRange; |
| }; |
| |
| Move<VkImageView> testedView = createImageView(vk, device, &imageViewParams); |
| Move<VkImageView> referenceView = makeImageView(vk, device, referenceImage.get(), imageViewType, m_parameters.testedFormat, subresourceRange); |
| Move<VkImageView> resultView = makeImageView(vk, device, resultImage.get(), imageViewType, m_parameters.resultFormat, |
| makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, resultImageInfo.extent.depth, 0u, resultImageInfo.arrayLayers)); |
| |
| Move<VkDescriptorSetLayout> descriptorSetLayout = DescriptorSetLayoutBuilder() |
| .addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT) |
| .addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_COMPUTE_BIT) |
| .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT) |
| .build(vk, device); |
| Move<VkDescriptorPool> descriptorPool = DescriptorPoolBuilder() |
| .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, compressedImageInfo.arrayLayers) |
| .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, compressedImageInfo.arrayLayers) |
| .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, resultImageInfo.arrayLayers) |
| .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, resultImageInfo.arrayLayers); |
| |
| Move<VkDescriptorSet> descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout); |
| const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout)); |
| const Unique<VkPipeline> pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule)); |
| |
| const VkDeviceSize bufferSizeCompresed = getCompressedImageSizeInBytes(m_parameters.testedFormat, m_parameters.imageSize); |
| const VkDeviceSize bufferSizeUncompressed = getImageSizeBytes(IVec3((int)extentUnCompressed.width, (int)extentUnCompressed.height, (int)extentUnCompressed.depth), m_parameters.resultFormat); |
| VkBufferCreateInfo compressedBufferCI = makeBufferCreateInfo(bufferSizeCompresed, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); |
| VkBufferCreateInfo uncompressedBufferCI = makeBufferCreateInfo(bufferSizeUncompressed, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT); |
| Buffer inBuffer (vk, device, allocator, compressedBufferCI, MemoryRequirement::HostVisible); |
| Buffer resultBuffer (vk, device, allocator, uncompressedBufferCI, MemoryRequirement::HostVisible); |
| Move<VkSampler> sampler; |
| |
| // generate data for compressed image and copy it to in buffer |
| { |
| vector<deUint8> generatedData; |
| generatedData.resize(static_cast<size_t>(bufferSizeCompresed)); |
| |
| auto blocks = getCompressedImageResolutionInBlocks(m_parameters.testedFormat, m_parameters.imageSize); |
| tcu::astc::generateRandomValidBlocks(generatedData.data(), |
| blocks.x() * blocks.y() * blocks.z(), |
| mapVkCompressedFormat(m_parameters.testedFormat), |
| tcu::TexDecompressionParams::ASTCMODE_LDR, |
| 1); |
| |
| const Allocation& alloc = inBuffer.getAllocation(); |
| deMemcpy(alloc.getHostPtr(), generatedData.data(), generatedData.size()); |
| flushAlloc(vk, device, alloc); |
| } |
| |
| { |
| const VkSamplerCreateInfo createInfo = |
| { |
| VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, //VkStructureType sType; |
| DE_NULL, //const void* pNext; |
| 0u, //VkSamplerCreateFlags flags; |
| VK_FILTER_NEAREST, //VkFilter magFilter; |
| VK_FILTER_NEAREST, //VkFilter minFilter; |
| VK_SAMPLER_MIPMAP_MODE_NEAREST, //VkSamplerMipmapMode mipmapMode; |
| VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, //VkSamplerAddressMode addressModeU; |
| VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, //VkSamplerAddressMode addressModeV; |
| VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, //VkSamplerAddressMode addressModeW; |
| 0.0f, //float mipLodBias; |
| VK_FALSE, //VkBool32 anisotropyEnable; |
| 1.0f, //float maxAnisotropy; |
| VK_FALSE, //VkBool32 compareEnable; |
| VK_COMPARE_OP_EQUAL, //VkCompareOp compareOp; |
| 0.0f, //float minLod; |
| 1.0f, //float maxLod; |
| VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, //VkBorderColor borderColor; |
| VK_FALSE, //VkBool32 unnormalizedCoordinates; |
| }; |
| sampler = createSampler(vk, device, &createInfo); |
| } |
| |
| VkDescriptorImageInfo descriptorImageInfos[] = |
| { |
| makeDescriptorImageInfo(*sampler, *testedView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), |
| makeDescriptorImageInfo(*sampler, *referenceView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL), |
| makeDescriptorImageInfo(DE_NULL, *resultView, VK_IMAGE_LAYOUT_GENERAL), |
| }; |
| DescriptorSetUpdateBuilder() |
| .writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorImageInfos[0]) |
| .writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorImageInfos[1]) |
| .writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfos[2]) |
| .update(vk, device); |
| |
| beginCommandBuffer(vk, *cmdBuffer); |
| { |
| // copy input buffer to tested and reference images |
| { |
| Image* inImages[] = { &testedImage, &referenceImage }; |
| for (Image* image : inImages) |
| { |
| const VkImageMemoryBarrier preCopyImageBarrier = makeImageMemoryBarrier( |
| 0u, VK_ACCESS_TRANSFER_WRITE_BIT, |
| VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, |
| image->get(), subresourceRange); |
| |
| const VkBufferMemoryBarrier flushHostCopyBarrier = makeBufferMemoryBarrier( |
| VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, |
| inBuffer.get(), 0ull, bufferSizeCompresed); |
| |
| vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, |
| (VkDependencyFlags)0, 0u, (const VkMemoryBarrier*)DE_NULL, 1u, &flushHostCopyBarrier, 1u, &preCopyImageBarrier); |
| |
| const VkBufferImageCopy copyRegion = |
| { |
| 0ull, //VkDeviceSize bufferOffset; |
| 0u, //deUint32 bufferRowLength; |
| 0u, //deUint32 bufferImageHeight; |
| makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), //VkImageSubresourceLayers imageSubresource; |
| makeOffset3D(0, 0, 0), //VkOffset3D imageOffset; |
| extentCompressed, //VkExtent3D imageExtent; |
| }; |
| |
| vk.cmdCopyBufferToImage(*cmdBuffer, inBuffer.get(), image->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region); |
| } |
| } |
| |
| // bind pipeline and descriptors |
| vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); |
| vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); |
| |
| { |
| const VkImageMemoryBarrier preShaderImageBarriers[] = |
| { |
| makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, |
| testedImage.get(), subresourceRange), |
| |
| makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, |
| VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, |
| referenceImage.get(), subresourceRange), |
| |
| makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, |
| VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, |
| resultImage.get(), subresourceRange) |
| }; |
| |
| vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, |
| (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0u, (const VkBufferMemoryBarrier*)DE_NULL, |
| DE_LENGTH_OF_ARRAY(preShaderImageBarriers), preShaderImageBarriers); |
| } |
| |
| vk.cmdDispatch(*cmdBuffer, extentUnCompressed.width, extentUnCompressed.height, extentUnCompressed.depth); |
| |
| { |
| const VkImageMemoryBarrier postShaderImageBarriers[] = |
| { |
| makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, |
| VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, |
| resultImage.get(), subresourceRange) |
| }; |
| |
| vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, |
| (VkDependencyFlags)0, 0u, (const VkMemoryBarrier*)DE_NULL, 0u, (const VkBufferMemoryBarrier*)DE_NULL, |
| DE_LENGTH_OF_ARRAY(postShaderImageBarriers), postShaderImageBarriers); |
| } |
| |
| const VkBufferImageCopy copyRegion = |
| { |
| 0ull, // VkDeviceSize bufferOffset; |
| 0u, // deUint32 bufferRowLength; |
| 0u, // deUint32 bufferImageHeight; |
| makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u), // VkImageSubresourceLayers imageSubresource; |
| makeOffset3D(0, 0, 0), // VkOffset3D imageOffset; |
| resultImageInfo.extent, // VkExtent3D imageExtent; |
| }; |
| vk.cmdCopyImageToBuffer(*cmdBuffer, resultImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, resultBuffer.get(), 1u, ©Region); |
| |
| { |
| const VkBufferMemoryBarrier postCopyBufferBarrier[] = |
| { |
| makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, |
| resultBuffer.get(), 0ull, bufferSizeUncompressed), |
| }; |
| |
| vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, |
| (VkDependencyFlags)0, 0u, (const VkMemoryBarrier*)DE_NULL, DE_LENGTH_OF_ARRAY(postCopyBufferBarrier), postCopyBufferBarrier, |
| 0u, (const VkImageMemoryBarrier*)DE_NULL); |
| } |
| } |
| endCommandBuffer(vk, *cmdBuffer); |
| submitCommandsAndWait(vk, device, queue, *cmdBuffer); |
| |
| const Allocation& resultAlloc = resultBuffer.getAllocation(); |
| invalidateAlloc(vk, device, resultAlloc); |
| |
| // verification is done in shader - here we just check if one of pixels has wrong value |
| const size_t numBytes = static_cast<size_t>(bufferSizeUncompressed); |
| deUint8* result = static_cast<deUint8*>(resultAlloc.getHostPtr()); |
| for (size_t i = 0 ; i < numBytes ; i += 4) |
| { |
| // expected result should be around 128 (if reference is same as tested mode then we return 0.5) |
| if ((result[i] < 100) || (result[i] > 150)) |
| return TestStatus::fail("Fail"); |
| } |
| |
| return TestStatus::pass("Pass"); |
| } |
| |
| class AstcDecodeModeCase : public TestCase |
| { |
| public: |
| AstcDecodeModeCase (TestContext& testCtx, |
| const std::string& name, |
| const std::string& desc, |
| const TestParameters& parameters); |
| virtual void checkSupport (Context& context) const; |
| void initPrograms (SourceCollections& programCollection) const; |
| TestInstance* createInstance (Context& context) const; |
| |
| protected: |
| |
| const TestParameters m_parameters; |
| }; |
| |
| AstcDecodeModeCase::AstcDecodeModeCase (TestContext& testCtx, |
| const std::string& name, |
| const std::string& desc, |
| const TestParameters& parameters) |
| : TestCase (testCtx, name, desc) |
| , m_parameters (parameters) |
| { |
| } |
| |
| void AstcDecodeModeCase::checkSupport (Context& context) const |
| { |
| const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); |
| const InstanceInterface& vk = context.getInstanceInterface(); |
| |
| context.requireDeviceFunctionality("VK_EXT_astc_decode_mode"); |
| if (!getPhysicalDeviceFeatures(vk, physicalDevice).textureCompressionASTC_LDR) |
| TCU_THROW(NotSupportedError, "textureCompressionASTC_LDR not supported"); |
| |
| VkImageFormatProperties imageFormatProperties; |
| if (VK_ERROR_FORMAT_NOT_SUPPORTED == vk.getPhysicalDeviceImageFormatProperties(physicalDevice, m_parameters.testedFormat, |
| mapImageType(m_parameters.imageType), VK_IMAGE_TILING_OPTIMAL, |
| m_parameters.testedImageUsage, 0u, &imageFormatProperties)) |
| TCU_THROW(NotSupportedError, "Operation not supported with this image format"); |
| |
| if (VK_ERROR_FORMAT_NOT_SUPPORTED == vk.getPhysicalDeviceImageFormatProperties(physicalDevice, m_parameters.resultFormat, |
| mapImageType(m_parameters.imageType), VK_IMAGE_TILING_OPTIMAL, |
| m_parameters.resultImageUsage, 0u, &imageFormatProperties)) |
| TCU_THROW(NotSupportedError, "Operation not supported with this image format"); |
| |
| if ((m_parameters.testedDecodeMode == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) && |
| !context.getASTCDecodeFeaturesEXT().decodeModeSharedExponent) |
| TCU_THROW(NotSupportedError, "decodeModeSharedExponent not supported"); |
| |
| VkFormatProperties properties; |
| context.getInstanceInterface().getPhysicalDeviceFormatProperties(context.getPhysicalDevice(), m_parameters.resultFormat, &properties); |
| if (!(properties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) |
| TCU_THROW(NotSupportedError, "Format storage feature not supported"); |
| } |
| |
| void AstcDecodeModeCase::initPrograms (vk::SourceCollections& programCollection) const |
| { |
| DE_ASSERT(m_parameters.imageSize.x() > 0); |
| DE_ASSERT(m_parameters.imageSize.y() > 0); |
| |
| const string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_parameters.resultFormat)); |
| const string imageTypeStr = getShaderImageType(mapVkFormat(m_parameters.resultFormat), m_parameters.imageType); |
| |
| std::ostringstream src; |
| src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" |
| << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n\n" |
| << "layout (binding = 0) uniform sampler2D compressed_tested;\n" |
| << "layout (binding = 1) uniform sampler2D compressed_reference;\n" |
| << "layout (binding = 2, " << formatQualifierStr << ") writeonly uniform " << imageTypeStr << " result;\n" |
| << "void main (void)\n" |
| << "{\n" |
| << " const vec2 pixels_resolution = vec2(gl_NumWorkGroups.xy);\n" |
| << " const vec2 cord = vec2(gl_GlobalInvocationID.xy) / vec2(pixels_resolution);\n" |
| << " const ivec2 pos = ivec2(gl_GlobalInvocationID.xy); \n" |
| << " vec4 tested = texture(compressed_tested, cord);\n" |
| << " vec4 reference = texture(compressed_reference, cord);\n"; |
| |
| // special case for e5b9g9r9 decode mode that was set on unorm astc formats |
| // here negative values are clamped to zero and alpha is set to 1 |
| if (m_parameters.testedIsUnorm && (m_parameters.testedDecodeMode == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32)) |
| src << " reference = max(vec4(0,0,0,1), reference);\n" |
| " float result_color = 0.5 * float(distance(tested, reference) < 0.01);\n"; |
| else |
| src << " float result_color = 0.5 * float(distance(tested, reference) < 0.01);\n"; |
| |
| src << " imageStore(result, pos, vec4(result_color));\n" |
| << "}\n"; |
| |
| programCollection.glslSources.add("comp") << glu::ComputeSource(src.str()); |
| } |
| |
| TestInstance* AstcDecodeModeCase::createInstance (Context& context) const |
| { |
| return new BasicComputeTestInstance(context, m_parameters); |
| } |
| |
| } // anonymous ns |
| |
| tcu::TestCaseGroup* createImageAstcDecodeModeTests (tcu::TestContext& testCtx) |
| { |
| struct FormatData |
| { |
| VkFormat format; |
| std::string name; |
| deBool isUnorm; |
| }; |
| const FormatData astcFormats[] = |
| { |
| { VK_FORMAT_ASTC_4x4_UNORM_BLOCK, "4x4_unorm", DE_TRUE }, |
| { VK_FORMAT_ASTC_4x4_SRGB_BLOCK, "4x4_srgb", DE_FALSE }, |
| { VK_FORMAT_ASTC_5x4_UNORM_BLOCK, "5x4_unorm", DE_TRUE }, |
| { VK_FORMAT_ASTC_5x4_SRGB_BLOCK, "5x4_srgb", DE_FALSE }, |
| { VK_FORMAT_ASTC_5x5_UNORM_BLOCK, "5x5_unorm", DE_TRUE }, |
| { VK_FORMAT_ASTC_5x5_SRGB_BLOCK, "5x5_srgb", DE_FALSE }, |
| { VK_FORMAT_ASTC_6x5_UNORM_BLOCK, "6x5_unorm", DE_TRUE }, |
| { VK_FORMAT_ASTC_6x5_SRGB_BLOCK, "6x5_srgb", DE_FALSE }, |
| { VK_FORMAT_ASTC_6x6_UNORM_BLOCK, "6x6_unorm", DE_TRUE }, |
| { VK_FORMAT_ASTC_6x6_SRGB_BLOCK, "6x6_srgb", DE_FALSE }, |
| { VK_FORMAT_ASTC_8x5_UNORM_BLOCK, "8x5_unorm", DE_TRUE }, |
| { VK_FORMAT_ASTC_8x5_SRGB_BLOCK, "8x5_srgb", DE_FALSE }, |
| { VK_FORMAT_ASTC_8x6_UNORM_BLOCK, "8x6_unorm", DE_TRUE }, |
| { VK_FORMAT_ASTC_8x6_SRGB_BLOCK, "8x6_srgb", DE_FALSE }, |
| { VK_FORMAT_ASTC_8x8_UNORM_BLOCK, "8x8_unorm", DE_TRUE }, |
| { VK_FORMAT_ASTC_8x8_SRGB_BLOCK, "8x8_srgb", DE_FALSE }, |
| { VK_FORMAT_ASTC_10x5_UNORM_BLOCK, "10x5_unorm", DE_TRUE }, |
| { VK_FORMAT_ASTC_10x5_SRGB_BLOCK, "10x5_srgb", DE_FALSE }, |
| { VK_FORMAT_ASTC_10x6_UNORM_BLOCK, "10x6_unorm", DE_TRUE }, |
| { VK_FORMAT_ASTC_10x6_SRGB_BLOCK, "10x6_srgb", DE_FALSE }, |
| { VK_FORMAT_ASTC_10x8_UNORM_BLOCK, "10x8_unorm", DE_TRUE }, |
| { VK_FORMAT_ASTC_10x8_SRGB_BLOCK, "10x8_srgb", DE_FALSE }, |
| { VK_FORMAT_ASTC_10x10_UNORM_BLOCK, "10x10_unorm", DE_TRUE }, |
| { VK_FORMAT_ASTC_10x10_SRGB_BLOCK, "10x10_srgb", DE_FALSE }, |
| { VK_FORMAT_ASTC_12x10_UNORM_BLOCK, "12x10_unorm", DE_TRUE }, |
| { VK_FORMAT_ASTC_12x10_SRGB_BLOCK, "12x10_srgb", DE_FALSE }, |
| { VK_FORMAT_ASTC_12x12_UNORM_BLOCK, "12x12_unorm", DE_TRUE }, |
| { VK_FORMAT_ASTC_12x12_SRGB_BLOCK, "12x12_srgb", DE_FALSE }, |
| }; |
| |
| struct DecodeModeData |
| { |
| VkFormat mode; |
| std::string name; |
| }; |
| const DecodeModeData decodeModes[] = |
| { |
| { VK_FORMAT_R16G16B16A16_SFLOAT, "r16g16b16a16_sfloat" }, |
| { VK_FORMAT_R8G8B8A8_UNORM, "r8g8b8a8_unorm" }, |
| { VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, "e5b9g9r9_ufloat_pack32" } |
| }; |
| |
| MovePtr<tcu::TestCaseGroup> astcDecodeModeTests(new tcu::TestCaseGroup(testCtx, "astc_decode_mode", "Intermediate decoding precision cases")); |
| for (const FormatData& format : astcFormats) |
| { |
| for (const DecodeModeData& mode : decodeModes) |
| { |
| const TestParameters parameters = |
| { |
| IMAGE_TYPE_2D, |
| UVec3(64u, 64u, 1u), |
| format.format, |
| format.isUnorm, |
| mode.mode, |
| VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, |
| VK_FORMAT_R8G8B8A8_UNORM, |
| VK_IMAGE_USAGE_STORAGE_BIT |
| }; |
| |
| std::string name = format.name + "_to_" + mode.name; |
| astcDecodeModeTests->addChild(new AstcDecodeModeCase(testCtx, name, "", parameters)); |
| } |
| } |
| |
| return astcDecodeModeTests.release(); |
| } |
| |
| } // image |
| } // vkt |