/*------------------------------------------------------------------------ * Vulkan Conformance Tests * ------------------------ * * Copyright (c) 2017 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 vktImageCompressionTranscodingSupport.cpp * \brief Compression transcoding support *//*--------------------------------------------------------------------*/ #include "vktImageCompressionTranscodingSupport.hpp" #include "vktImageLoadStoreUtil.hpp" #include "deUniquePtr.hpp" #include "deStringUtil.hpp" #include "deSharedPtr.hpp" #include "deRandom.hpp" #include "vktTestCaseUtil.hpp" #include "vkPrograms.hpp" #include "vkImageUtil.hpp" #include "vkBarrierUtil.hpp" #include "vktImageTestsUtil.hpp" #include "vkBuilderUtil.hpp" #include "vkRef.hpp" #include "vkRefUtil.hpp" #include "vkTypeUtil.hpp" #include "vkQueryUtil.hpp" #include "vkCmdUtil.hpp" #include "vkObjUtil.hpp" #include "tcuTextureUtil.hpp" #include "tcuTexture.hpp" #include "tcuCompressedTexture.hpp" #include "tcuVectorType.hpp" #include "tcuResource.hpp" #include "tcuImageIO.hpp" #include "tcuImageCompare.hpp" #include "tcuTestLog.hpp" #include "tcuRGBA.hpp" #include "tcuSurface.hpp" #include 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 tcu::Resource; using tcu::Archive; using tcu::ConstPixelBufferAccess; using de::MovePtr; using de::SharedPtr; using de::Random; typedef SharedPtr > ImageSp; typedef SharedPtr > ImageViewSp; typedef SharedPtr > SharedVkDescriptorSet; enum ShaderType { SHADER_TYPE_COMPUTE, SHADER_TYPE_FRAGMENT, SHADER_TYPE_LAST }; enum Operation { OPERATION_IMAGE_LOAD, OPERATION_TEXEL_FETCH, OPERATION_TEXTURE, OPERATION_IMAGE_STORE, OPERATION_ATTACHMENT_READ, OPERATION_ATTACHMENT_WRITE, OPERATION_TEXTURE_READ, OPERATION_TEXTURE_WRITE, OPERATION_LAST }; struct TestParameters { Operation operation; ShaderType shader; UVec3 size; deUint32 layers; ImageType imageType; VkFormat formatCompressed; VkFormat formatUncompressed; deUint32 imagesCount; VkImageUsageFlags compressedImageUsage; VkImageUsageFlags compressedImageViewUsage; VkImageUsageFlags uncompressedImageUsage; bool useMipmaps; VkFormat formatForVerify; bool formatIsASTC; }; template inline SharedPtr > makeVkSharedPtr (Move move) { return SharedPtr >(new Move(move)); } template inline SharedPtr > makeVkSharedPtr (MovePtr movePtr) { return SharedPtr >(new MovePtr(movePtr)); } const deUint32 SINGLE_LEVEL = 1u; const deUint32 SINGLE_LAYER = 1u; enum BinaryCompareMode { COMPARE_MODE_NORMAL, COMPARE_MODE_ALLOW_ASTC_ERROR_COLOUR_WARNING, }; enum BinaryCompareResult { COMPARE_RESULT_OK, COMPARE_RESULT_ASTC_QUALITY_WARNING, COMPARE_RESULT_FAILED, }; const deUint32 ASTC_LDR_ERROR_COLOUR = 0xFFFF00FF; const deUint32 ASTC_HDR_ERROR_COLOUR = 0x00000000; static BinaryCompareResult BinaryCompare(const void *reference, const void *result, VkDeviceSize sizeInBytes, VkFormat formatForVerify, BinaryCompareMode mode) { DE_UNREF(formatForVerify); // Compare quickly using deMemCmp if (deMemCmp(reference, result, (size_t)sizeInBytes) == 0) { return COMPARE_RESULT_OK; } // If deMemCmp indicated a mismatch, we can re-check with a manual comparison of // the ref and res images that allows for ASTC error colour mismatches if the ASTC // comparison mode was selected. This slows down the affected ASTC tests if you // didn't pass in the first comparison, but means in the general case the // comparion is still fast. else if (mode == COMPARE_MODE_ALLOW_ASTC_ERROR_COLOUR_WARNING) { bool bWarn = false; bool bFail = false; const deUint32 *pui32RefVal = (deUint32*)reference; const deUint32 *pui32ResVal = (deUint32*)result; DE_ASSERT(formatForVerify == VK_FORMAT_R8G8B8A8_UNORM); size_t numPixels = (size_t)(sizeInBytes / 4) /* bytes */; for (size_t i = 0; i < numPixels; i++) { const deUint32 ref = *pui32RefVal++; const deUint32 res = *pui32ResVal++; if (ref != res) { // QualityWarning !1231: If the astc pixel was the ASTC LDR error colour // and the result image has the HDR error colour (or vice versa as the test // cases below sometimes reverse the operands) then issue a quality warning // instead of a failure. if ((ref == ASTC_LDR_ERROR_COLOUR && res == ASTC_HDR_ERROR_COLOUR) || (ref == ASTC_HDR_ERROR_COLOUR && res == ASTC_LDR_ERROR_COLOUR)) { bWarn = true; } else { bFail = true; } } } if (!bFail) { return (bWarn) ? (COMPARE_RESULT_ASTC_QUALITY_WARNING) : (COMPARE_RESULT_OK); } } return COMPARE_RESULT_FAILED; } static bool FormatIsASTC(VkFormat format) { return deInRange32(format, VK_FORMAT_ASTC_4x4_UNORM_BLOCK, VK_FORMAT_ASTC_12x12_SRGB_BLOCK); } static TestStatus TestStatusASTCQualityWarning() { return TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "ASTC HDR error colour output instead of LDR error colour"); } class BasicTranscodingTestInstance : public TestInstance { public: BasicTranscodingTestInstance (Context& context, const TestParameters& parameters); virtual TestStatus iterate (void) = 0; protected: void generateData (deUint8* toFill, const size_t size, const VkFormat format, const deUint32 layer = 0u, const deUint32 level = 0u); deUint32 getLevelCount (); deUint32 getLayerCount (); UVec3 getLayerDims (); vector getMipLevelSizes (UVec3 baseSize); vector getCompressedMipLevelSizes (const VkFormat compressedFormat, const vector& uncompressedSizes); const TestParameters m_parameters; const deUint32 m_blockWidth; const deUint32 m_blockHeight; const deUint32 m_levelCount; const UVec3 m_layerSize; // Detected error colour mismatch while verifying image. Output // the ASTC quality warning instead of a pass bool m_bASTCErrorColourMismatch; private: deUint32 findMipMapLevelCount (); }; deUint32 BasicTranscodingTestInstance::findMipMapLevelCount () { deUint32 levelCount = 1; // We cannot use mipmap levels which have resolution below block size. // Reduce number of mipmap levels if (m_parameters.useMipmaps) { deUint32 w = m_parameters.size.x(); deUint32 h = m_parameters.size.y(); DE_ASSERT(m_blockWidth > 0u && m_blockHeight > 0u); while (w > m_blockWidth && h > m_blockHeight) { w >>= 1; h >>= 1; if (w > m_blockWidth && h > m_blockHeight) levelCount++; } DE_ASSERT((m_parameters.size.x() >> (levelCount - 1u)) >= m_blockWidth); DE_ASSERT((m_parameters.size.y() >> (levelCount - 1u)) >= m_blockHeight); } return levelCount; } BasicTranscodingTestInstance::BasicTranscodingTestInstance (Context& context, const TestParameters& parameters) : TestInstance (context) , m_parameters (parameters) , m_blockWidth (getBlockWidth(m_parameters.formatCompressed)) , m_blockHeight (getBlockHeight(m_parameters.formatCompressed)) , m_levelCount (findMipMapLevelCount()) , m_layerSize (getLayerSize(m_parameters.imageType, m_parameters.size)) , m_bASTCErrorColourMismatch(false) { DE_ASSERT(deLog2Floor32(m_parameters.size.x()) == deLog2Floor32(m_parameters.size.y())); } deUint32 BasicTranscodingTestInstance::getLevelCount() { return m_levelCount; } deUint32 BasicTranscodingTestInstance::getLayerCount() { return m_parameters.layers; } UVec3 BasicTranscodingTestInstance::getLayerDims() { return m_layerSize; } vector BasicTranscodingTestInstance::getMipLevelSizes (UVec3 baseSize) { vector levelSizes; const deUint32 levelCount = getLevelCount(); baseSize.z() = 1u; levelSizes.push_back(baseSize); if (m_parameters.imageType == IMAGE_TYPE_1D) { baseSize.y() = 1u; while (levelSizes.size() < levelCount && (baseSize.x() != 1)) { baseSize.x() = deMax32(baseSize.x() >> 1, 1); levelSizes.push_back(baseSize); } } else { while (levelSizes.size() < levelCount && (baseSize.x() != 1 || baseSize.y() != 1)) { baseSize.x() = deMax32(baseSize.x() >> 1, 1); baseSize.y() = deMax32(baseSize.y() >> 1, 1); levelSizes.push_back(baseSize); } } DE_ASSERT(levelSizes.size() == getLevelCount()); return levelSizes; } vector BasicTranscodingTestInstance::getCompressedMipLevelSizes (const VkFormat compressedFormat, const vector& uncompressedSizes) { vector levelSizes; vector::const_iterator it; for (it = uncompressedSizes.begin(); it != uncompressedSizes.end(); it++) levelSizes.push_back(getCompressedImageResolutionInBlocks(compressedFormat, *it)); return levelSizes; } void BasicTranscodingTestInstance::generateData (deUint8* toFill, const size_t size, const VkFormat format, const deUint32 layer, const deUint32 level) { const deUint8 pattern[] = { // 64-bit values 0x11, 0x11, 0x11, 0x11, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Positive infinity 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Negative infinity 0x7F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // Start of a signalling NaN (NANS) 0x7F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // End of a signalling NaN (NANS) 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // Start of a signalling NaN (NANS) 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // End of a signalling NaN (NANS) 0x7F, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Start of a quiet NaN (NANQ) 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // End of of a quiet NaN (NANQ) 0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Start of a quiet NaN (NANQ) 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // End of a quiet NaN (NANQ) // 32-bit values 0x7F, 0x80, 0x00, 0x00, // Positive infinity 0xFF, 0x80, 0x00, 0x00, // Negative infinity 0x7F, 0x80, 0x00, 0x01, // Start of a signalling NaN (NANS) 0x7F, 0xBF, 0xFF, 0xFF, // End of a signalling NaN (NANS) 0xFF, 0x80, 0x00, 0x01, // Start of a signalling NaN (NANS) 0xFF, 0xBF, 0xFF, 0xFF, // End of a signalling NaN (NANS) 0x7F, 0xC0, 0x00, 0x00, // Start of a quiet NaN (NANQ) 0x7F, 0xFF, 0xFF, 0xFF, // End of of a quiet NaN (NANQ) 0xFF, 0xC0, 0x00, 0x00, // Start of a quiet NaN (NANQ) 0xFF, 0xFF, 0xFF, 0xFF, // End of a quiet NaN (NANQ) 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, }; deUint8* start = toFill; size_t sizeToRnd = size; // Pattern part if (layer == 0 && level == 0 && size >= 2 * sizeof(pattern)) { // Rotated pattern for (size_t i = 0; i < sizeof(pattern); i++) start[sizeof(pattern) - i - 1] = pattern[i]; start += sizeof(pattern); sizeToRnd -= sizeof(pattern); // Direct pattern deMemcpy(start, pattern, sizeof(pattern)); start += sizeof(pattern); sizeToRnd -= sizeof(pattern); } // Random part { DE_ASSERT(sizeToRnd % sizeof(deUint32) == 0); deUint32* start32 = reinterpret_cast(start); size_t sizeToRnd32 = sizeToRnd / sizeof(deUint32); deUint32 seed = (layer << 24) ^ (level << 16) ^ static_cast(format); Random rnd (seed); for (size_t i = 0; i < sizeToRnd32; i++) start32[i] = rnd.getUint32(); } { // Remove certain values that may not be preserved based on the uncompressed view format if (isSnormFormat(m_parameters.formatUncompressed)) { for (size_t i = 0; i < size; i += 2) { // SNORM fix: due to write operation in SNORM format // replaces 0x00 0x80 to 0x01 0x80 if (toFill[i] == 0x00 && toFill[i+1] == 0x80) toFill[i+1] = 0x81; } } else if (isFloatFormat(m_parameters.formatUncompressed)) { tcu::TextureFormat textureFormat = mapVkFormat(m_parameters.formatUncompressed); if (textureFormat.type == tcu::TextureFormat::HALF_FLOAT) { for (size_t i = 0; i < size; i += 2) { // HALF_FLOAT fix: remove INF and NaN if ((toFill[i+1] & 0x7C) == 0x7C) toFill[i+1] = 0x00; } } else if (textureFormat.type == tcu::TextureFormat::FLOAT) { for (size_t i = 0; i < size; i += 4) { // HALF_FLOAT fix: remove INF and NaN if ((toFill[i+1] & 0x7C) == 0x7C) toFill[i+1] = 0x00; } for (size_t i = 0; i < size; i += 4) { // FLOAT fix: remove INF, NaN, and denorm // Little endian fix if (((toFill[i+3] & 0x7F) == 0x7F && (toFill[i+2] & 0x80) == 0x80) || ((toFill[i+3] & 0x7F) == 0x00 && (toFill[i+2] & 0x80) == 0x00)) toFill[i+3] = 0x01; // Big endian fix if (((toFill[i+0] & 0x7F) == 0x7F && (toFill[i+1] & 0x80) == 0x80) || ((toFill[i+0] & 0x7F) == 0x00 && (toFill[i+1] & 0x80) == 0x00)) toFill[i+0] = 0x01; } } } } } class BasicComputeTestInstance : public BasicTranscodingTestInstance { public: BasicComputeTestInstance (Context& context, const TestParameters& parameters); TestStatus iterate (void); protected: struct ImageData { deUint32 getImagesCount (void) { return static_cast(images.size()); } deUint32 getImageViewCount (void) { return static_cast(imagesViews.size()); } deUint32 getImageInfoCount (void) { return static_cast(imagesInfos.size()); } VkImage getImage (const deUint32 ndx) { return **images[ndx]->get(); } VkImageView getImageView (const deUint32 ndx) { return **imagesViews[ndx]; } VkImageCreateInfo getImageInfo (const deUint32 ndx) { return imagesInfos[ndx]; } void addImage (MovePtr image) { images.push_back(makeVkSharedPtr(image)); } void addImageView (Move imageView) { imagesViews.push_back(makeVkSharedPtr(imageView));} void addImageInfo (const VkImageCreateInfo imageInfo) { imagesInfos.push_back(imageInfo); } void resetViews () { imagesViews.clear(); } private: vector images; vector imagesViews; vector imagesInfos; }; void copyDataToImage (const VkCommandBuffer& cmdBuffer, ImageData& imageData, const vector& mipMapSizes, const bool isCompressed); virtual void executeShader (const VkCommandBuffer& cmdBuffer, const VkDescriptorSetLayout& descriptorSetLayout, const VkDescriptorPool& descriptorPool, vector& imageData); bool copyResultAndCompare (const VkCommandBuffer& cmdBuffer, const VkImage& uncompressed, const VkDeviceSize offset, const UVec3& size); void descriptorSetUpdate (VkDescriptorSet descriptorSet, const VkDescriptorImageInfo* descriptorImageInfos); void createImageInfos (ImageData& imageData, const vector& mipMapSizes, const bool isCompressed); bool decompressImage (const VkCommandBuffer& cmdBuffer, vector& imageData, const vector& mipMapSizes); vector m_data; }; BasicComputeTestInstance::BasicComputeTestInstance (Context& context, const TestParameters& parameters) :BasicTranscodingTestInstance (context, parameters) { } TestStatus BasicComputeTestInstance::iterate (void) { const DeviceInterface& vk = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); Allocator& allocator = m_context.getDefaultAllocator(); const Unique cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); const Unique cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); const UVec3 fullSize (m_parameters.size.x(), m_parameters.size.y(), 1); const vector mipMapSizes = m_parameters.useMipmaps ? getMipLevelSizes (getLayerDims()) : vector(1, fullSize); vector imageData (m_parameters.imagesCount); const deUint32 compressedNdx = 0u; const deUint32 resultImageNdx = m_parameters.imagesCount -1u; for (deUint32 imageNdx = 0u; imageNdx < m_parameters.imagesCount; ++imageNdx) { const bool isCompressed = compressedNdx == imageNdx ? true : false; createImageInfos(imageData[imageNdx], mipMapSizes, isCompressed); for (deUint32 infoNdx = 0u; infoNdx < imageData[imageNdx].getImageInfoCount(); ++infoNdx) { imageData[imageNdx].addImage(MovePtr(new Image(vk, device, allocator, imageData[imageNdx].getImageInfo(infoNdx), MemoryRequirement::Any))); if (isCompressed) { const VkImageViewUsageCreateInfo imageViewUsageKHR = { VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR, //VkStructureType sType; DE_NULL, //const void* pNext; m_parameters.compressedImageUsage, //VkImageUsageFlags usage; }; for (deUint32 mipNdx = 0u; mipNdx < mipMapSizes.size(); ++mipNdx) for (deUint32 layerNdx = 0u; layerNdx < getLayerCount(); ++layerNdx) { imageData[imageNdx].addImageView(makeImageView(vk, device, imageData[imageNdx].getImage(infoNdx), mapImageViewType(m_parameters.imageType), m_parameters.formatUncompressed, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipNdx, 1u, layerNdx, 1u), &imageViewUsageKHR)); } } else { imageData[imageNdx].addImageView(makeImageView(vk, device, imageData[imageNdx].getImage(infoNdx), mapImageViewType(m_parameters.imageType), m_parameters.formatUncompressed, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u))); } } } { size_t size = 0ull; for(deUint32 mipNdx = 0u; mipNdx < mipMapSizes.size(); ++mipNdx) { size += static_cast(getCompressedImageSizeInBytes(m_parameters.formatCompressed, mipMapSizes[mipNdx]) * getLayerCount()); } m_data.resize(size); generateData (&m_data[0], m_data.size(), m_parameters.formatCompressed); } switch(m_parameters.operation) { case OPERATION_IMAGE_LOAD: case OPERATION_TEXEL_FETCH: case OPERATION_TEXTURE: copyDataToImage(*cmdBuffer, imageData[compressedNdx], mipMapSizes, true); break; case OPERATION_IMAGE_STORE: copyDataToImage(*cmdBuffer, imageData[1], mipMapSizes, false); break; default: DE_ASSERT(false); break; } { Move descriptorSetLayout; Move descriptorPool; DescriptorSetLayoutBuilder descriptorSetLayoutBuilder; DescriptorPoolBuilder descriptorPoolBuilder; for (deUint32 imageNdx = 0u; imageNdx < m_parameters.imagesCount; ++imageNdx) { switch(m_parameters.operation) { case OPERATION_IMAGE_LOAD: case OPERATION_IMAGE_STORE: descriptorSetLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT); descriptorPoolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, imageData[0].getImageViewCount()); break; case OPERATION_TEXEL_FETCH: case OPERATION_TEXTURE: descriptorSetLayoutBuilder.addSingleBinding((compressedNdx == imageNdx) ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT); descriptorPoolBuilder.addType((compressedNdx == imageNdx) ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, imageData[0].getImageViewCount()); break; default: DE_ASSERT(false); break; } } descriptorSetLayout = descriptorSetLayoutBuilder.build(vk, device); descriptorPool = descriptorPoolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, imageData[0].getImageViewCount()); executeShader(*cmdBuffer, *descriptorSetLayout, *descriptorPool, imageData); { VkDeviceSize offset = 0ull; for (deUint32 mipNdx = 0u; mipNdx < mipMapSizes.size(); ++mipNdx) for (deUint32 layerNdx = 0u; layerNdx < getLayerCount(); ++layerNdx) { const deUint32 imageNdx = layerNdx + mipNdx * getLayerCount(); const UVec3 size = UVec3(imageData[resultImageNdx].getImageInfo(imageNdx).extent.width, imageData[resultImageNdx].getImageInfo(imageNdx).extent.height, imageData[resultImageNdx].getImageInfo(imageNdx).extent.depth); if (!copyResultAndCompare(*cmdBuffer, imageData[resultImageNdx].getImage(imageNdx), offset, size)) return TestStatus::fail("Fail"); offset += getCompressedImageSizeInBytes(m_parameters.formatCompressed, mipMapSizes[mipNdx]); } } } if (!decompressImage(*cmdBuffer, imageData, mipMapSizes)) return TestStatus::fail("Fail"); if (m_bASTCErrorColourMismatch) { DE_ASSERT(m_parameters.formatIsASTC); return TestStatusASTCQualityWarning(); } return TestStatus::pass("Pass"); } void BasicComputeTestInstance::copyDataToImage (const VkCommandBuffer& cmdBuffer, ImageData& imageData, const vector& mipMapSizes, const bool isCompressed) { const DeviceInterface& vk = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); const VkQueue queue = m_context.getUniversalQueue(); Allocator& allocator = m_context.getDefaultAllocator(); Buffer imageBuffer (vk, device, allocator, makeBufferCreateInfo(m_data.size(), VK_BUFFER_USAGE_TRANSFER_SRC_BIT), MemoryRequirement::HostVisible); VkDeviceSize offset = 0ull; { const Allocation& alloc = imageBuffer.getAllocation(); deMemcpy(alloc.getHostPtr(), &m_data[0], m_data.size()); flushAlloc(vk, device, alloc); } beginCommandBuffer(vk, cmdBuffer); const VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask 0u, //deUint32 baseMipLevel imageData.getImageInfo(0u).mipLevels, //deUint32 levelCount 0u, //deUint32 baseArrayLayer imageData.getImageInfo(0u).arrayLayers //deUint32 layerCount }; for (deUint32 imageNdx = 0u; imageNdx < imageData.getImagesCount(); ++imageNdx) { const VkImageMemoryBarrier preCopyImageBarrier = makeImageMemoryBarrier( 0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, imageData.getImage(imageNdx), subresourceRange); const VkBufferMemoryBarrier FlushHostCopyBarrier = makeBufferMemoryBarrier( VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, imageBuffer.get(), 0ull, m_data.size()); vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0u, (const VkMemoryBarrier*)DE_NULL, 1u, &FlushHostCopyBarrier, 1u, &preCopyImageBarrier); for (deUint32 mipNdx = 0u; mipNdx < imageData.getImageInfo(imageNdx).mipLevels; ++mipNdx) { const VkExtent3D imageExtent = isCompressed ? makeExtent3D(mipMapSizes[mipNdx]) : imageData.getImageInfo(imageNdx).extent; const VkBufferImageCopy copyRegion = { offset, //VkDeviceSize bufferOffset; 0u, //deUint32 bufferRowLength; 0u, //deUint32 bufferImageHeight; makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, mipNdx, 0u, imageData.getImageInfo(imageNdx).arrayLayers), //VkImageSubresourceLayers imageSubresource; makeOffset3D(0, 0, 0), //VkOffset3D imageOffset; imageExtent, //VkExtent3D imageExtent; }; vk.cmdCopyBufferToImage(cmdBuffer, imageBuffer.get(), imageData.getImage(imageNdx), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region); offset += getCompressedImageSizeInBytes(m_parameters.formatCompressed, UVec3(isCompressed ? imageExtent.width : imageExtent.width * m_blockWidth, isCompressed? imageExtent.height :imageExtent.height * m_blockHeight,imageExtent.depth)) * imageData.getImageInfo(imageNdx).arrayLayers; } } endCommandBuffer(vk, cmdBuffer); submitCommandsAndWait(vk, device, queue, cmdBuffer); } void BasicComputeTestInstance::executeShader (const VkCommandBuffer& cmdBuffer, const VkDescriptorSetLayout& descriptorSetLayout, const VkDescriptorPool& descriptorPool, vector& imageData) { const DeviceInterface& vk = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); const VkQueue queue = m_context.getUniversalQueue(); const Unique shaderModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0)); vector descriptorSets (imageData[0].getImageViewCount()); const Unique pipelineLayout (makePipelineLayout(vk, device, descriptorSetLayout)); const Unique pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule)); Move sampler; { 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; 0.0f, //float maxLod; VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, //VkBorderColor borderColor; VK_FALSE, //VkBool32 unnormalizedCoordinates; }; sampler = createSampler(vk, device, &createInfo); } vector descriptorImageInfos (descriptorSets.size() * m_parameters.imagesCount); for (deUint32 viewNdx = 0u; viewNdx < descriptorSets.size(); ++viewNdx) { const deUint32 descriptorNdx = viewNdx * m_parameters.imagesCount; for (deUint32 imageNdx = 0; imageNdx < m_parameters.imagesCount; ++imageNdx) { descriptorImageInfos[descriptorNdx+imageNdx] = makeDescriptorImageInfo(*sampler, imageData[imageNdx].getImageView(viewNdx), VK_IMAGE_LAYOUT_GENERAL); } } for (deUint32 ndx = 0u; ndx < descriptorSets.size(); ++ndx) descriptorSets[ndx] = makeVkSharedPtr(makeDescriptorSet(vk, device, descriptorPool, descriptorSetLayout)); beginCommandBuffer(vk, cmdBuffer); { const VkImageSubresourceRange compressedRange = { VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask 0u, //deUint32 baseMipLevel imageData[0].getImageInfo(0u).mipLevels, //deUint32 levelCount 0u, //deUint32 baseArrayLayer imageData[0].getImageInfo(0u).arrayLayers //deUint32 layerCount }; const VkImageSubresourceRange uncompressedRange = { VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask 0u, //deUint32 baseMipLevel 1u, //deUint32 levelCount 0u, //deUint32 baseArrayLayer 1u //deUint32 layerCount }; vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); vector preShaderImageBarriers; preShaderImageBarriers.resize(descriptorSets.size() + 1u); for (deUint32 imageNdx = 0u; imageNdx < imageData[1].getImagesCount(); ++imageNdx) { preShaderImageBarriers[imageNdx]= makeImageMemoryBarrier( VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, imageData[1].getImage(imageNdx), uncompressedRange); } preShaderImageBarriers[descriptorSets.size()] = makeImageMemoryBarrier( VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, imageData[0].getImage(0), compressedRange); vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0u, (const VkMemoryBarrier*)DE_NULL, 0u, (const VkBufferMemoryBarrier*)DE_NULL, static_cast(preShaderImageBarriers.size()), &preShaderImageBarriers[0]); for (deUint32 ndx = 0u; ndx (offset)], static_cast(imageResultSize)) == 0ull) return true; return false; } void BasicComputeTestInstance::descriptorSetUpdate (VkDescriptorSet descriptorSet, const VkDescriptorImageInfo* descriptorImageInfos) { const DeviceInterface& vk = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); DescriptorSetUpdateBuilder descriptorSetUpdateBuilder; switch(m_parameters.operation) { case OPERATION_IMAGE_LOAD: case OPERATION_IMAGE_STORE: { for (deUint32 bindingNdx = 0u; bindingNdx < m_parameters.imagesCount; ++bindingNdx) descriptorSetUpdateBuilder.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bindingNdx), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfos[bindingNdx]); break; } case OPERATION_TEXEL_FETCH: case OPERATION_TEXTURE: { for (deUint32 bindingNdx = 0u; bindingNdx < m_parameters.imagesCount; ++bindingNdx) { descriptorSetUpdateBuilder.writeSingle(descriptorSet, DescriptorSetUpdateBuilder::Location::binding(bindingNdx), bindingNdx == 0u ? VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfos[bindingNdx]); } break; } default: DE_ASSERT(false); } descriptorSetUpdateBuilder.update(vk, device); } void BasicComputeTestInstance::createImageInfos (ImageData& imageData, const vector& mipMapSizes, const bool isCompressed) { const VkImageType imageType = mapImageType(m_parameters.imageType); if (isCompressed) { VkFormatProperties properties; m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(), m_parameters.formatCompressed, &properties); if (!(properties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) TCU_THROW(NotSupportedError, "Format storage feature not supported"); const VkExtent3D extentCompressed = makeExtent3D(getLayerSize(m_parameters.imageType, m_parameters.size)); const VkImageCreateInfo compressedInfo = { 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_KHR | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR, // VkImageCreateFlags flags; imageType, // VkImageType imageType; m_parameters.formatCompressed, // VkFormat format; extentCompressed, // VkExtent3D extent; static_cast(mipMapSizes.size()), // deUint32 mipLevels; getLayerCount(), // 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; }; imageData.addImageInfo(compressedInfo); } else { UVec3 size = m_parameters.size; if (m_parameters.imageType == IMAGE_TYPE_1D) { size.y() = 1; } size.z() = 1; const VkExtent3D originalResolutionInBlocks = makeExtent3D(getCompressedImageResolutionInBlocks(m_parameters.formatCompressed, size)); for (size_t mipNdx = 0ull; mipNdx < mipMapSizes.size(); ++mipNdx) for (size_t layerNdx = 0ull; layerNdx < getLayerCount(); ++layerNdx) { const VkExtent3D extentUncompressed = m_parameters.useMipmaps ? makeExtent3D(getCompressedImageResolutionInBlocks(m_parameters.formatCompressed, mipMapSizes[mipNdx])) : originalResolutionInBlocks; const VkImageCreateInfo uncompressedInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; 0u, // VkImageCreateFlags flags; imageType, // VkImageType imageType; m_parameters.formatUncompressed, // VkFormat format; extentUncompressed, // VkExtent3D extent; 1u, // deUint32 mipLevels; 1u, // deUint32 arrayLayers; VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; m_parameters.uncompressedImageUsage | VK_IMAGE_USAGE_SAMPLED_BIT, // VkImageUsageFlags usage; VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 0u, // deUint32 queueFamilyIndexCount; DE_NULL, // const deUint32* pQueueFamilyIndices; VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; }; imageData.addImageInfo(uncompressedInfo); } } } bool BasicComputeTestInstance::decompressImage (const VkCommandBuffer& cmdBuffer, vector& imageData, const vector& mipMapSizes) { const DeviceInterface& vk = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); const VkQueue queue = m_context.getUniversalQueue(); Allocator& allocator = m_context.getDefaultAllocator(); const Unique shaderModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("decompress"), 0)); const VkImage& compressed = imageData[0].getImage(0); const VkImageType imageType = mapImageType(m_parameters.imageType); for (deUint32 ndx = 0u; ndx < imageData.size(); ndx++) imageData[ndx].resetViews(); for (deUint32 mipNdx = 0u; mipNdx < mipMapSizes.size(); ++mipNdx) for (deUint32 layerNdx = 0u; layerNdx < getLayerCount(); ++layerNdx) { const bool layoutShaderReadOnly = (layerNdx % 2u) == 1; const deUint32 imageNdx = layerNdx + mipNdx * getLayerCount(); const VkExtent3D extentCompressed = imageType == VK_IMAGE_TYPE_1D ? makeExtent3D(mipMapSizes[mipNdx].x(), 1, mipMapSizes[mipNdx].z()) : makeExtent3D(mipMapSizes[mipNdx]); const VkImage& uncompressed = imageData[m_parameters.imagesCount -1].getImage(imageNdx); const VkExtent3D extentUncompressed = imageData[m_parameters.imagesCount -1].getImageInfo(imageNdx).extent; const VkDeviceSize bufferSizeComp = getCompressedImageSizeInBytes(m_parameters.formatCompressed, mipMapSizes[mipNdx]); VkFormatProperties properties; m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(), m_parameters.formatForVerify, &properties); if (!(properties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) TCU_THROW(NotSupportedError, "Format storage feature not supported"); const VkImageCreateInfo decompressedImageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; 0u, // VkImageCreateFlags flags; imageType, // VkImageType imageType; m_parameters.formatForVerify, // 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_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; }; const VkImageCreateInfo compressedImageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; 0u, // VkImageCreateFlags flags; imageType, // VkImageType imageType; m_parameters.formatCompressed, // 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 VkImageUsageFlags compressedViewUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; const VkImageViewUsageCreateInfo compressedViewUsageCI = { VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO_KHR, //VkStructureType sType; DE_NULL, //const void* pNext; compressedViewUsageFlags, //VkImageUsageFlags usage; }; const VkImageViewType imageViewType (mapImageViewType(m_parameters.imageType)); Image resultImage (vk, device, allocator, decompressedImageInfo, MemoryRequirement::Any); Image referenceImage (vk, device, allocator, decompressedImageInfo, MemoryRequirement::Any); Image uncompressedImage (vk, device, allocator, compressedImageInfo, MemoryRequirement::Any); Move resultView = makeImageView(vk, device, resultImage.get(), imageViewType, decompressedImageInfo.format, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, decompressedImageInfo.extent.depth, 0u, decompressedImageInfo.arrayLayers)); Move referenceView = makeImageView(vk, device, referenceImage.get(), imageViewType, decompressedImageInfo.format, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, decompressedImageInfo.extent.depth, 0u, decompressedImageInfo.arrayLayers)); Move uncompressedView = makeImageView(vk, device, uncompressedImage.get(), imageViewType, m_parameters.formatCompressed, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, compressedImageInfo.extent.depth, 0u, compressedImageInfo.arrayLayers)); Move compressedView = makeImageView(vk, device, compressed, imageViewType, m_parameters.formatCompressed, makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, mipNdx, 1u, layerNdx, 1u), &compressedViewUsageCI); Move 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) .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT) .build(vk, device); Move descriptorPool = DescriptorPoolBuilder() .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, decompressedImageInfo.arrayLayers) .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, decompressedImageInfo.arrayLayers) .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, decompressedImageInfo.arrayLayers) .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, decompressedImageInfo.arrayLayers) .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, decompressedImageInfo.arrayLayers); Move descriptorSet = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout); const Unique pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout)); const Unique pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule)); const VkDeviceSize bufferSize = getImageSizeBytes(IVec3((int)extentCompressed.width, (int)extentCompressed.height, (int)extentCompressed.depth), m_parameters.formatForVerify); Buffer resultBuffer (vk, device, allocator, makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible); Buffer referenceBuffer (vk, device, allocator, makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible); Buffer transferBuffer (vk, device, allocator, makeBufferCreateInfo(bufferSizeComp, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT), MemoryRequirement::HostVisible); Move sampler; { 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, *uncompressedView, layoutShaderReadOnly ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL), makeDescriptorImageInfo(*sampler, *compressedView, layoutShaderReadOnly ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL), makeDescriptorImageInfo(DE_NULL, *resultView, VK_IMAGE_LAYOUT_GENERAL), makeDescriptorImageInfo(DE_NULL, *referenceView, 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]) .writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(3u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfos[3]) .update(vk, device); beginCommandBuffer(vk, cmdBuffer); { const VkImageSubresourceRange subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask 0u, //deUint32 baseMipLevel 1u, //deUint32 levelCount 0u, //deUint32 baseArrayLayer 1u //deUint32 layerCount }; const VkImageSubresourceRange subresourceRangeComp = { VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask mipNdx, //deUint32 baseMipLevel 1u, //deUint32 levelCount layerNdx, //deUint32 baseArrayLayer 1u //deUint32 layerCount }; 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; decompressedImageInfo.extent, // VkExtent3D imageExtent; }; const VkBufferImageCopy compressedCopyRegion = { 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; extentUncompressed, // VkExtent3D imageExtent; }; { const VkBufferMemoryBarrier preCopyBufferBarriers = makeBufferMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, transferBuffer.get(), 0ull, bufferSizeComp); vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1u, &preCopyBufferBarriers, 0u, (const VkImageMemoryBarrier*)DE_NULL); } vk.cmdCopyImageToBuffer(cmdBuffer, uncompressed, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, transferBuffer.get(), 1u, &compressedCopyRegion); { const VkBufferMemoryBarrier postCopyBufferBarriers = makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, transferBuffer.get(), 0ull, bufferSizeComp); const VkImageMemoryBarrier preCopyImageBarriers = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, uncompressedImage.get(), subresourceRange); vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0u, (const VkMemoryBarrier*)DE_NULL, 1u, &postCopyBufferBarriers, 1u, &preCopyImageBarriers); } vk.cmdCopyBufferToImage(cmdBuffer, transferBuffer.get(), uncompressedImage.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, ©Region); 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, layoutShaderReadOnly ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL, uncompressedImage.get(), subresourceRange), makeImageMemoryBarrier(0, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, layoutShaderReadOnly ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL, compressed, subresourceRangeComp), makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, resultImage.get(), subresourceRange), makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, referenceImage.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, extentCompressed.width, extentCompressed.height, extentCompressed.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), makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, referenceImage.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); } vk.cmdCopyImageToBuffer(cmdBuffer, resultImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, resultBuffer.get(), 1u, ©Region); vk.cmdCopyImageToBuffer(cmdBuffer, referenceImage.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, referenceBuffer.get(), 1u, ©Region); { const VkBufferMemoryBarrier postCopyBufferBarrier[] = { makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, resultBuffer.get(), 0ull, bufferSize), makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, referenceBuffer.get(), 0ull, bufferSize), }; 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(); const Allocation& referenceAlloc = referenceBuffer.getAllocation(); invalidateAlloc(vk, device, resultAlloc); invalidateAlloc(vk, device, referenceAlloc); BinaryCompareMode compareMode = (m_parameters.formatIsASTC) ?(COMPARE_MODE_ALLOW_ASTC_ERROR_COLOUR_WARNING) :(COMPARE_MODE_NORMAL); BinaryCompareResult res = BinaryCompare(referenceAlloc.getHostPtr(), resultAlloc.getHostPtr(), (size_t)bufferSize, m_parameters.formatForVerify, compareMode); if (res == COMPARE_RESULT_FAILED) { ConstPixelBufferAccess resultPixels (mapVkFormat(decompressedImageInfo.format), decompressedImageInfo.extent.width, decompressedImageInfo.extent.height, decompressedImageInfo.extent.depth, resultAlloc.getHostPtr()); ConstPixelBufferAccess referencePixels (mapVkFormat(decompressedImageInfo.format), decompressedImageInfo.extent.width, decompressedImageInfo.extent.height, decompressedImageInfo.extent.depth, referenceAlloc.getHostPtr()); if(!fuzzyCompare(m_context.getTestContext().getLog(), "Image Comparison", "Image Comparison", resultPixels, referencePixels, 0.001f, tcu::COMPARE_LOG_EVERYTHING)) return false; } else if (res == COMPARE_RESULT_ASTC_QUALITY_WARNING) { m_bASTCErrorColourMismatch = true; } } return true; } class ImageStoreComputeTestInstance : public BasicComputeTestInstance { public: ImageStoreComputeTestInstance (Context& context, const TestParameters& parameters); protected: virtual void executeShader (const VkCommandBuffer& cmdBuffer, const VkDescriptorSetLayout& descriptorSetLayout, const VkDescriptorPool& descriptorPool, vector& imageData); private: }; ImageStoreComputeTestInstance::ImageStoreComputeTestInstance (Context& context, const TestParameters& parameters) :BasicComputeTestInstance (context, parameters) { } void ImageStoreComputeTestInstance::executeShader (const VkCommandBuffer& cmdBuffer, const VkDescriptorSetLayout& descriptorSetLayout, const VkDescriptorPool& descriptorPool, vector& imageData) { const DeviceInterface& vk = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); const VkQueue queue = m_context.getUniversalQueue(); const Unique shaderModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("comp"), 0)); vector descriptorSets (imageData[0].getImageViewCount()); const Unique pipelineLayout (makePipelineLayout(vk, device, descriptorSetLayout)); const Unique pipeline (makeComputePipeline(vk, device, *pipelineLayout, *shaderModule)); Move sampler; { 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; 0.0f, //float maxLod; VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, //VkBorderColor borderColor; VK_TRUE, //VkBool32 unnormalizedCoordinates; }; sampler = createSampler(vk, device, &createInfo); } vector descriptorImageInfos (descriptorSets.size() * m_parameters.imagesCount); for (deUint32 viewNdx = 0u; viewNdx < descriptorSets.size(); ++viewNdx) { const deUint32 descriptorNdx = viewNdx * m_parameters.imagesCount; for (deUint32 imageNdx = 0u; imageNdx < m_parameters.imagesCount; ++imageNdx) { descriptorImageInfos[descriptorNdx+imageNdx] = makeDescriptorImageInfo(*sampler, imageData[imageNdx].getImageView(viewNdx), VK_IMAGE_LAYOUT_GENERAL); } } for (deUint32 ndx = 0u; ndx < descriptorSets.size(); ++ndx) descriptorSets[ndx] = makeVkSharedPtr(makeDescriptorSet(vk, device, descriptorPool, descriptorSetLayout)); beginCommandBuffer(vk, cmdBuffer); { const VkImageSubresourceRange compressedRange = { VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask 0u, //deUint32 baseMipLevel imageData[0].getImageInfo(0).mipLevels, //deUint32 levelCount 0u, //deUint32 baseArrayLayer imageData[0].getImageInfo(0).arrayLayers //deUint32 layerCount }; const VkImageSubresourceRange uncompressedRange = { VK_IMAGE_ASPECT_COLOR_BIT, //VkImageAspectFlags aspectMask 0u, //deUint32 baseMipLevel 1u, //deUint32 levelCount 0u, //deUint32 baseArrayLayer 1u //deUint32 layerCount }; vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline); vector preShaderImageBarriers (descriptorSets.size() * 2u + 1u); for (deUint32 imageNdx = 0u; imageNdx < imageData[1].getImagesCount(); ++imageNdx) { preShaderImageBarriers[imageNdx] = makeImageMemoryBarrier( VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, imageData[1].getImage(imageNdx), uncompressedRange); preShaderImageBarriers[imageNdx + imageData[1].getImagesCount()] = makeImageMemoryBarrier( VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, imageData[2].getImage(imageNdx), uncompressedRange); } preShaderImageBarriers[preShaderImageBarriers.size()-1] = makeImageMemoryBarrier( VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, imageData[0].getImage(0u), compressedRange); vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, (VkDependencyFlags)0, 0u, (const VkMemoryBarrier*)DE_NULL, 0u, (const VkBufferMemoryBarrier*)DE_NULL, static_cast(preShaderImageBarriers.size()), &preShaderImageBarriers[0]); for (deUint32 ndx = 0u; ndx & data, const deUint32 layer, const deUint32 level); VkDeviceSize getUncompressedImageData (const VkFormat format, const UVec3& size, std::vector& data, const deUint32 layer, const deUint32 level); virtual void prepareData (); virtual void prepareVertexBuffer (); virtual void transcodeRead (); virtual void transcodeWrite (); bool verifyDecompression (const std::vector& refCompressedData, const de::MovePtr& resCompressedImage, const deUint32 layer, const deUint32 level, const UVec3& mipmapDims); typedef std::vector RawDataVector; typedef SharedPtr RawDataPtr; typedef std::vector LevelData; typedef std::vector FullImageData; FullImageData m_srcData; FullImageData m_dstData; typedef SharedPtr ImagePtr; typedef std::vector LevelImages; typedef std::vector ImagesArray; ImagesArray m_uncompressedImages; MovePtr m_compressedImage; VkImageViewUsageCreateInfo m_imageViewUsageKHR; VkImageViewUsageCreateInfo* m_srcImageViewUsageKHR; VkImageViewUsageCreateInfo* m_dstImageViewUsageKHR; std::vector m_compressedImageResVec; std::vector m_uncompressedImageResVec; VkFormat m_srcFormat; VkFormat m_dstFormat; VkImageUsageFlags m_srcImageUsageFlags; VkImageUsageFlags m_dstImageUsageFlags; std::vector m_srcImageResolutions; std::vector m_dstImageResolutions; MovePtr m_vertexBuffer; deUint32 m_vertexCount; VkDeviceSize m_vertexBufferOffset; }; GraphicsAttachmentsTestInstance::GraphicsAttachmentsTestInstance (Context& context, const TestParameters& parameters) : BasicTranscodingTestInstance(context, parameters) , m_srcData() , m_dstData() , m_uncompressedImages() , m_compressedImage() , m_imageViewUsageKHR() , m_srcImageViewUsageKHR() , m_dstImageViewUsageKHR() , m_compressedImageResVec() , m_uncompressedImageResVec() , m_srcFormat() , m_dstFormat() , m_srcImageUsageFlags() , m_dstImageUsageFlags() , m_srcImageResolutions() , m_dstImageResolutions() , m_vertexBuffer() , m_vertexCount(0u) , m_vertexBufferOffset(0ull) { } TestStatus GraphicsAttachmentsTestInstance::iterate (void) { prepareData(); prepareVertexBuffer(); for (deUint32 levelNdx = 0; levelNdx < getLevelCount(); ++levelNdx) for (deUint32 layerNdx = 0; layerNdx < getLayerCount(); ++layerNdx) DE_ASSERT(m_srcData[levelNdx][layerNdx]->size() == m_dstData[levelNdx][layerNdx]->size()); if (isWriteToCompressedOperation()) transcodeWrite(); else transcodeRead(); for (deUint32 levelNdx = 0; levelNdx < getLevelCount(); ++levelNdx) for (deUint32 layerNdx = 0; layerNdx < getLayerCount(); ++layerNdx) if (isWriteToCompressedOperation()) { if (!verifyDecompression(*m_srcData[levelNdx][layerNdx], m_compressedImage, levelNdx, layerNdx, m_compressedImageResVec[levelNdx])) return TestStatus::fail("Images difference detected"); } else { if (!verifyDecompression(*m_dstData[levelNdx][layerNdx], m_compressedImage, levelNdx, layerNdx, m_compressedImageResVec[levelNdx])) return TestStatus::fail("Images difference detected"); } if (m_bASTCErrorColourMismatch) { DE_ASSERT(m_parameters.formatIsASTC); return TestStatusASTCQualityWarning(); } return TestStatus::pass("Pass"); } void GraphicsAttachmentsTestInstance::prepareData () { VkImageViewUsageCreateInfo* imageViewUsageKHRNull = (VkImageViewUsageCreateInfo*)DE_NULL; m_imageViewUsageKHR = makeImageViewUsageCreateInfo(m_parameters.compressedImageViewUsage); m_srcImageViewUsageKHR = isWriteToCompressedOperation() ? imageViewUsageKHRNull : &m_imageViewUsageKHR; m_dstImageViewUsageKHR = isWriteToCompressedOperation() ? &m_imageViewUsageKHR : imageViewUsageKHRNull; m_srcFormat = isWriteToCompressedOperation() ? m_parameters.formatUncompressed : m_parameters.formatCompressed; m_dstFormat = isWriteToCompressedOperation() ? m_parameters.formatCompressed : m_parameters.formatUncompressed; m_srcImageUsageFlags = isWriteToCompressedOperation() ? m_parameters.uncompressedImageUsage : m_parameters.compressedImageUsage; m_dstImageUsageFlags = isWriteToCompressedOperation() ? m_parameters.compressedImageUsage : m_parameters.uncompressedImageUsage; m_compressedImageResVec = getMipLevelSizes(getLayerDims()); m_uncompressedImageResVec = getCompressedMipLevelSizes(m_parameters.formatCompressed, m_compressedImageResVec); m_srcImageResolutions = isWriteToCompressedOperation() ? m_uncompressedImageResVec : m_compressedImageResVec; m_dstImageResolutions = isWriteToCompressedOperation() ? m_compressedImageResVec : m_uncompressedImageResVec; m_srcData.resize(getLevelCount()); m_dstData.resize(getLevelCount()); m_uncompressedImages.resize(getLevelCount()); for (deUint32 levelNdx = 0; levelNdx < getLevelCount(); ++levelNdx) { m_srcData[levelNdx].resize(getLayerCount()); m_dstData[levelNdx].resize(getLayerCount()); m_uncompressedImages[levelNdx].resize(getLayerCount()); for (deUint32 layerNdx = 0; layerNdx < getLayerCount(); ++layerNdx) { m_srcData[levelNdx][layerNdx] = SharedPtr(new RawDataVector); m_dstData[levelNdx][layerNdx] = SharedPtr(new RawDataVector); if (isWriteToCompressedOperation()) { getUncompressedImageData(m_srcFormat, m_srcImageResolutions[levelNdx], *m_srcData[levelNdx][layerNdx], layerNdx, levelNdx); m_dstData[levelNdx][layerNdx]->resize((size_t)getCompressedImageSizeInBytes(m_dstFormat, m_dstImageResolutions[levelNdx])); } else { getCompressedImageData(m_srcFormat, m_srcImageResolutions[levelNdx], *m_srcData[levelNdx][layerNdx], layerNdx, levelNdx); m_dstData[levelNdx][layerNdx]->resize((size_t)getUncompressedImageSizeInBytes(m_dstFormat, m_dstImageResolutions[levelNdx])); } DE_ASSERT(m_srcData[levelNdx][layerNdx]->size() == m_dstData[levelNdx][layerNdx]->size()); } } } void GraphicsAttachmentsTestInstance::prepareVertexBuffer () { const DeviceInterface& vk = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); Allocator& allocator = m_context.getDefaultAllocator(); const std::vector vertexArray = createFullscreenQuad(); const size_t vertexBufferSizeInBytes = vertexArray.size() * sizeof(vertexArray[0]); m_vertexCount = static_cast(vertexArray.size()); m_vertexBuffer = MovePtr(new Buffer(vk, device, allocator, makeBufferCreateInfo(vertexBufferSizeInBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible)); // Upload vertex data const Allocation& vertexBufferAlloc = m_vertexBuffer->getAllocation(); deMemcpy(vertexBufferAlloc.getHostPtr(), &vertexArray[0], vertexBufferSizeInBytes); flushAlloc(vk, device, vertexBufferAlloc); } void GraphicsAttachmentsTestInstance::transcodeRead () { const DeviceInterface& vk = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); const VkQueue queue = m_context.getUniversalQueue(); Allocator& allocator = m_context.getDefaultAllocator(); const VkImageCreateFlags* imgCreateFlagsOverride = DE_NULL; const VkImageCreateInfo srcImageCreateInfo = makeCreateImageInfo(m_srcFormat, m_parameters.imageType, m_srcImageResolutions[0], m_srcImageUsageFlags, imgCreateFlagsOverride, getLevelCount(), getLayerCount()); MovePtr srcImage (new Image(vk, device, allocator, srcImageCreateInfo, MemoryRequirement::Any)); const Unique vertShaderModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0)); const Unique fragShaderModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0)); const Unique renderPass (vkt::image::makeRenderPass(vk, device, m_parameters.formatUncompressed, m_parameters.formatUncompressed)); const Move descriptorSetLayout (DescriptorSetLayoutBuilder() .addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT) .build(vk, device)); const Move descriptorPool (DescriptorPoolBuilder() .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); const Move descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); const VkExtent2D renderSizeDummy (makeExtent2D(1u, 1u)); const Unique pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout)); const Unique pipeline (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertShaderModule, *fragShaderModule, renderSizeDummy, 1u, true)); const Unique cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); const Unique cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); for (deUint32 levelNdx = 0; levelNdx < getLevelCount(); ++levelNdx) { const UVec3& uncompressedImageRes = m_uncompressedImageResVec[levelNdx]; const UVec3& srcImageResolution = m_srcImageResolutions[levelNdx]; const UVec3& dstImageResolution = m_dstImageResolutions[levelNdx]; const size_t srcImageSizeInBytes = m_srcData[levelNdx][0]->size(); const size_t dstImageSizeInBytes = m_dstData[levelNdx][0]->size(); const UVec3 srcImageResBlocked = getCompressedImageResolutionBlockCeil(m_parameters.formatCompressed, srcImageResolution); const VkImageCreateInfo dstImageCreateInfo = makeCreateImageInfo(m_dstFormat, m_parameters.imageType, dstImageResolution, m_dstImageUsageFlags, imgCreateFlagsOverride, SINGLE_LEVEL, SINGLE_LAYER); const VkBufferCreateInfo srcImageBufferInfo = makeBufferCreateInfo(srcImageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); const MovePtr srcImageBuffer = MovePtr(new Buffer(vk, device, allocator, srcImageBufferInfo, MemoryRequirement::HostVisible)); const VkBufferCreateInfo dstImageBufferInfo = makeBufferCreateInfo(dstImageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT); MovePtr dstImageBuffer = MovePtr(new Buffer(vk, device, allocator, dstImageBufferInfo, MemoryRequirement::HostVisible)); const VkExtent2D renderSize (makeExtent2D(uncompressedImageRes.x(), uncompressedImageRes.y())); const VkViewport viewport = makeViewport(renderSize); const VkRect2D scissor = makeRect2D(renderSize); for (deUint32 layerNdx = 0; layerNdx < getLayerCount(); ++layerNdx) { const VkImageSubresourceRange srcSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, levelNdx, SINGLE_LEVEL, layerNdx, SINGLE_LAYER); const VkImageSubresourceRange dstSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, SINGLE_LEVEL, 0u, SINGLE_LAYER); Move srcImageView (makeImageView(vk, device, srcImage->get(), mapImageViewType(m_parameters.imageType), m_parameters.formatUncompressed, srcSubresourceRange, m_srcImageViewUsageKHR)); de::MovePtr dstImage (new Image(vk, device, allocator, dstImageCreateInfo, MemoryRequirement::Any)); Move dstImageView (makeImageView(vk, device, dstImage->get(), mapImageViewType(m_parameters.imageType), m_parameters.formatUncompressed, dstSubresourceRange, m_dstImageViewUsageKHR)); const VkBufferImageCopy srcCopyRegion = makeBufferImageCopy(srcImageResolution.x(), srcImageResolution.y(), levelNdx, layerNdx, srcImageResBlocked.x(), srcImageResBlocked.y()); const VkBufferMemoryBarrier srcCopyBufferBarrierPre = makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, srcImageBuffer->get(), 0ull, srcImageSizeInBytes); const VkImageMemoryBarrier srcCopyImageBarrierPre = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, srcImage->get(), srcSubresourceRange); const VkImageMemoryBarrier srcCopyImageBarrierPost = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, srcImage->get(), srcSubresourceRange); const VkBufferImageCopy dstCopyRegion = makeBufferImageCopy(dstImageResolution.x(), dstImageResolution.y()); const VkImageMemoryBarrier dstInitImageBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, dstImage->get(), dstSubresourceRange); const VkImageView attachmentBindInfos[] = { *srcImageView, *dstImageView }; const VkExtent2D framebufferSize (makeExtent2D(dstImageResolution[0], dstImageResolution[1])); const Move framebuffer (makeFramebuffer(vk, device, *renderPass, DE_LENGTH_OF_ARRAY(attachmentBindInfos), attachmentBindInfos, framebufferSize.width, framebufferSize.height, SINGLE_LAYER)); // Upload source image data const Allocation& alloc = srcImageBuffer->getAllocation(); deMemcpy(alloc.getHostPtr(), &m_srcData[levelNdx][layerNdx]->at(0), srcImageSizeInBytes); flushAlloc(vk, device, alloc); beginCommandBuffer(vk, *cmdBuffer); vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); // Copy buffer to image vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1u, &srcCopyBufferBarrierPre, 1u, &srcCopyImageBarrierPre); vk.cmdCopyBufferToImage(*cmdBuffer, srcImageBuffer->get(), srcImage->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &srcCopyRegion); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0u, DE_NULL, 1u, &srcCopyImageBarrierPost); // Define destination image layout vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0u, DE_NULL, 1u, &dstInitImageBarrier); beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderSize); const VkDescriptorImageInfo descriptorSrcImageInfo(makeDescriptorImageInfo(DE_NULL, *srcImageView, VK_IMAGE_LAYOUT_GENERAL)); DescriptorSetUpdateBuilder() .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &descriptorSrcImageInfo) .update(vk, device); vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &m_vertexBuffer->get(), &m_vertexBufferOffset); vk.cmdSetViewport(*cmdBuffer, 0u, 1u, &viewport); vk.cmdSetScissor(*cmdBuffer, 0u, 1u, &scissor); vk.cmdDraw(*cmdBuffer, (deUint32)m_vertexCount, 1, 0, 0); endRenderPass(vk, *cmdBuffer); const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier( VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, dstImage->get(), dstSubresourceRange); const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier( VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, dstImageBuffer->get(), 0ull, dstImageSizeInBytes); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &prepareForTransferBarrier); vk.cmdCopyImageToBuffer(*cmdBuffer, dstImage->get(), VK_IMAGE_LAYOUT_GENERAL, dstImageBuffer->get(), 1u, &dstCopyRegion); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, ©Barrier, 0, (const VkImageMemoryBarrier*)DE_NULL); endCommandBuffer(vk, *cmdBuffer); submitCommandsAndWait(vk, device, queue, *cmdBuffer); const Allocation& dstImageBufferAlloc = dstImageBuffer->getAllocation(); invalidateAlloc(vk, device, dstImageBufferAlloc); deMemcpy(&m_dstData[levelNdx][layerNdx]->at(0), dstImageBufferAlloc.getHostPtr(), dstImageSizeInBytes); } } m_compressedImage = srcImage; } void GraphicsAttachmentsTestInstance::transcodeWrite () { const DeviceInterface& vk = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); const VkQueue queue = m_context.getUniversalQueue(); Allocator& allocator = m_context.getDefaultAllocator(); const VkImageCreateFlags* imgCreateFlagsOverride = DE_NULL; const VkImageCreateInfo dstImageCreateInfo = makeCreateImageInfo(m_dstFormat, m_parameters.imageType, m_dstImageResolutions[0], m_dstImageUsageFlags, imgCreateFlagsOverride, getLevelCount(), getLayerCount()); MovePtr dstImage (new Image(vk, device, allocator, dstImageCreateInfo, MemoryRequirement::Any)); const Unique vertShaderModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0)); const Unique fragShaderModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0)); const Unique renderPass (vkt::image::makeRenderPass(vk, device, m_parameters.formatUncompressed, m_parameters.formatUncompressed)); const Move descriptorSetLayout (DescriptorSetLayoutBuilder() .addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT) .build(vk, device)); const Move descriptorPool (DescriptorPoolBuilder() .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); const Move descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); const VkExtent2D renderSizeDummy (makeExtent2D(1u, 1u)); const Unique pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout)); const Unique pipeline (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertShaderModule, *fragShaderModule, renderSizeDummy, 1u, true)); const Unique cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); const Unique cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); for (deUint32 levelNdx = 0; levelNdx < getLevelCount(); ++levelNdx) { const UVec3& uncompressedImageRes = m_uncompressedImageResVec[levelNdx]; const UVec3& srcImageResolution = m_srcImageResolutions[levelNdx]; const UVec3& dstImageResolution = m_dstImageResolutions[levelNdx]; const UVec3 dstImageResBlocked = getCompressedImageResolutionBlockCeil(m_parameters.formatCompressed, dstImageResolution); const size_t srcImageSizeInBytes = m_srcData[levelNdx][0]->size(); const size_t dstImageSizeInBytes = m_dstData[levelNdx][0]->size(); const VkImageCreateInfo srcImageCreateInfo = makeCreateImageInfo(m_srcFormat, m_parameters.imageType, srcImageResolution, m_srcImageUsageFlags, imgCreateFlagsOverride, SINGLE_LEVEL, SINGLE_LAYER); const VkExtent2D renderSize (makeExtent2D(uncompressedImageRes.x(), uncompressedImageRes.y())); const VkViewport viewport = makeViewport(renderSize); const VkRect2D scissor = makeRect2D(renderSize); for (deUint32 layerNdx = 0; layerNdx < getLayerCount(); ++layerNdx) { const VkBufferCreateInfo srcImageBufferInfo = makeBufferCreateInfo(srcImageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); const MovePtr srcImageBuffer = MovePtr(new Buffer(vk, device, allocator, srcImageBufferInfo, MemoryRequirement::HostVisible)); const VkBufferCreateInfo dstImageBufferInfo = makeBufferCreateInfo(dstImageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT); MovePtr dstImageBuffer = MovePtr(new Buffer(vk, device, allocator, dstImageBufferInfo, MemoryRequirement::HostVisible)); const VkImageSubresourceRange srcSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, SINGLE_LEVEL, 0u, SINGLE_LAYER); const VkImageSubresourceRange dstSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, levelNdx, SINGLE_LEVEL, layerNdx, SINGLE_LAYER); Move dstImageView (makeImageView(vk, device, dstImage->get(), mapImageViewType(m_parameters.imageType), m_parameters.formatUncompressed, dstSubresourceRange, m_dstImageViewUsageKHR)); de::MovePtr srcImage (new Image(vk, device, allocator, srcImageCreateInfo, MemoryRequirement::Any)); Move srcImageView (makeImageView(vk, device, srcImage->get(), mapImageViewType(m_parameters.imageType), m_parameters.formatUncompressed, srcSubresourceRange, m_srcImageViewUsageKHR)); const VkBufferImageCopy srcCopyRegion = makeBufferImageCopy(srcImageResolution.x(), srcImageResolution.y(), 0u, 0u); const VkBufferMemoryBarrier srcCopyBufferBarrierPre = makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, srcImageBuffer->get(), 0ull, srcImageSizeInBytes); const VkImageMemoryBarrier srcCopyImageBarrierPre = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, srcImage->get(), srcSubresourceRange); const VkImageMemoryBarrier srcCopyImageBarrierPost = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_INPUT_ATTACHMENT_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, srcImage->get(), srcSubresourceRange); const VkBufferImageCopy dstCopyRegion = makeBufferImageCopy(dstImageResolution.x(), dstImageResolution.y(), levelNdx, layerNdx, dstImageResBlocked.x(), dstImageResBlocked.y()); const VkImageMemoryBarrier dstInitImageBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, dstImage->get(), dstSubresourceRange); const VkImageView attachmentBindInfos[] = { *srcImageView, *dstImageView }; const VkExtent2D framebufferSize (renderSize); const Move framebuffer (makeFramebuffer(vk, device, *renderPass, DE_LENGTH_OF_ARRAY(attachmentBindInfos), attachmentBindInfos, framebufferSize.width, framebufferSize.height, SINGLE_LAYER)); // Upload source image data const Allocation& alloc = srcImageBuffer->getAllocation(); deMemcpy(alloc.getHostPtr(), &m_srcData[levelNdx][layerNdx]->at(0), srcImageSizeInBytes); flushAlloc(vk, device, alloc); beginCommandBuffer(vk, *cmdBuffer); vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); // Copy buffer to image vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1u, &srcCopyBufferBarrierPre, 1u, &srcCopyImageBarrierPre); vk.cmdCopyBufferToImage(*cmdBuffer, srcImageBuffer->get(), srcImage->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &srcCopyRegion); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0u, DE_NULL, 1u, &srcCopyImageBarrierPost); // Define destination image layout vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0u, DE_NULL, 1u, &dstInitImageBarrier); beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderSize); const VkDescriptorImageInfo descriptorSrcImageInfo(makeDescriptorImageInfo(DE_NULL, *srcImageView, VK_IMAGE_LAYOUT_GENERAL)); DescriptorSetUpdateBuilder() .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &descriptorSrcImageInfo) .update(vk, device); vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &m_vertexBuffer->get(), &m_vertexBufferOffset); vk.cmdSetViewport(*cmdBuffer, 0u, 1u, &viewport); vk.cmdSetScissor(*cmdBuffer, 0u, 1u, &scissor); vk.cmdDraw(*cmdBuffer, (deUint32)m_vertexCount, 1, 0, 0); endRenderPass(vk, *cmdBuffer); const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier( VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, dstImage->get(), dstSubresourceRange); const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier( VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, dstImageBuffer->get(), 0ull, dstImageSizeInBytes); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &prepareForTransferBarrier); vk.cmdCopyImageToBuffer(*cmdBuffer, dstImage->get(), VK_IMAGE_LAYOUT_GENERAL, dstImageBuffer->get(), 1u, &dstCopyRegion); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, ©Barrier, 0, (const VkImageMemoryBarrier*)DE_NULL); endCommandBuffer(vk, *cmdBuffer); submitCommandsAndWait(vk, device, queue, *cmdBuffer); const Allocation& dstImageBufferAlloc = dstImageBuffer->getAllocation(); invalidateAlloc(vk, device, dstImageBufferAlloc); deMemcpy(&m_dstData[levelNdx][layerNdx]->at(0), dstImageBufferAlloc.getHostPtr(), dstImageSizeInBytes); } } m_compressedImage = dstImage; } bool GraphicsAttachmentsTestInstance::isWriteToCompressedOperation () { return (m_parameters.operation == OPERATION_ATTACHMENT_WRITE); } VkImageCreateInfo GraphicsAttachmentsTestInstance::makeCreateImageInfo (const VkFormat format, const ImageType type, const UVec3& size, const VkImageUsageFlags usageFlags, const VkImageCreateFlags* createFlags, const deUint32 levels, const deUint32 layers) { const VkImageType imageType = mapImageType(type); const VkImageCreateFlags imageCreateFlagsBase = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT; const VkImageCreateFlags imageCreateFlagsAddOn = isCompressedFormat(format) ? VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT_KHR | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR : 0; const VkImageCreateFlags imageCreateFlags = (createFlags != DE_NULL) ? *createFlags : (imageCreateFlagsBase | imageCreateFlagsAddOn); VkFormatProperties properties; m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(), format, &properties); if ((usageFlags & VK_IMAGE_USAGE_STORAGE_BIT) && !(properties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT)) TCU_THROW(NotSupportedError, "Format storage feature not supported"); if ((usageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) && !(properties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) TCU_THROW(NotSupportedError, "Format color attachment feature not supported"); if ((usageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) && !(properties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) && !(properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) TCU_THROW(NotSupportedError, "Format color/depth/stencil attachment feature not supported for input attachment usage"); const VkImageCreateInfo createImageInfo = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; DE_NULL, // const void* pNext; imageCreateFlags, // VkImageCreateFlags flags; imageType, // VkImageType imageType; format, // VkFormat format; makeExtent3D(getLayerSize(type, size)), // VkExtent3D extent; levels, // deUint32 mipLevels; layers, // deUint32 arrayLayers; VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; usageFlags, // VkImageUsageFlags usage; VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 0u, // deUint32 queueFamilyIndexCount; DE_NULL, // const deUint32* pQueueFamilyIndices; VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; }; return createImageInfo; } VkDeviceSize GraphicsAttachmentsTestInstance::getCompressedImageData (const VkFormat format, const UVec3& size, std::vector& data, const deUint32 layer, const deUint32 level) { VkDeviceSize sizeBytes = getCompressedImageSizeInBytes(format, size); data.resize((size_t)sizeBytes); generateData(&data[0], data.size(), format, layer, level); return sizeBytes; } VkDeviceSize GraphicsAttachmentsTestInstance::getUncompressedImageData (const VkFormat format, const UVec3& size, std::vector& data, const deUint32 layer, const deUint32 level) { tcu::IVec3 sizeAsIVec3 = tcu::IVec3(static_cast(size[0]), static_cast(size[1]), static_cast(size[2])); VkDeviceSize sizeBytes = getImageSizeBytes(sizeAsIVec3, format); data.resize((size_t)sizeBytes); generateData(&data[0], data.size(), format, layer, level); return sizeBytes; } bool GraphicsAttachmentsTestInstance::verifyDecompression (const std::vector& refCompressedData, const de::MovePtr& resCompressedImage, const deUint32 level, const deUint32 layer, const UVec3& mipmapDims) { const DeviceInterface& vk = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); const VkQueue queue = m_context.getUniversalQueue(); Allocator& allocator = m_context.getDefaultAllocator(); const bool layoutShaderReadOnly = (layer % 2u) == 1; const UVec3 mipmapDimsBlocked = getCompressedImageResolutionBlockCeil(m_parameters.formatCompressed, mipmapDims); const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, SINGLE_LEVEL, 0u, SINGLE_LAYER); const VkImageSubresourceRange resSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, level, SINGLE_LEVEL, layer, SINGLE_LAYER); const VkDeviceSize dstBufferSize = getUncompressedImageSizeInBytes(m_parameters.formatForVerify, mipmapDims); const VkImageUsageFlags refSrcImageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; const VkBufferCreateInfo refSrcImageBufferInfo (makeBufferCreateInfo(refCompressedData.size(), VK_BUFFER_USAGE_TRANSFER_SRC_BIT)); const MovePtr refSrcImageBuffer = MovePtr(new Buffer(vk, device, allocator, refSrcImageBufferInfo, MemoryRequirement::HostVisible)); const VkImageCreateFlags refSrcImageCreateFlags = 0; const VkImageCreateInfo refSrcImageCreateInfo = makeCreateImageInfo(m_parameters.formatCompressed, m_parameters.imageType, mipmapDimsBlocked, refSrcImageUsageFlags, &refSrcImageCreateFlags, SINGLE_LEVEL, SINGLE_LAYER); const MovePtr refSrcImage (new Image(vk, device, allocator, refSrcImageCreateInfo, MemoryRequirement::Any)); Move refSrcImageView (makeImageView(vk, device, refSrcImage->get(), mapImageViewType(m_parameters.imageType), m_parameters.formatCompressed, subresourceRange)); const VkImageUsageFlags resSrcImageUsageFlags = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; const VkImageViewUsageCreateInfo resSrcImageViewUsageKHR = makeImageViewUsageCreateInfo(resSrcImageUsageFlags); Move resSrcImageView (makeImageView(vk, device, resCompressedImage->get(), mapImageViewType(m_parameters.imageType), m_parameters.formatCompressed, resSubresourceRange, &resSrcImageViewUsageKHR)); const VkImageCreateFlags refDstImageCreateFlags = 0; const VkImageUsageFlags refDstImageUsageFlags = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; const VkImageCreateInfo refDstImageCreateInfo = makeCreateImageInfo(m_parameters.formatForVerify, m_parameters.imageType, mipmapDims, refDstImageUsageFlags, &refDstImageCreateFlags, SINGLE_LEVEL, SINGLE_LAYER); const MovePtr refDstImage (new Image(vk, device, allocator, refDstImageCreateInfo, MemoryRequirement::Any)); const Move refDstImageView (makeImageView(vk, device, refDstImage->get(), mapImageViewType(m_parameters.imageType), m_parameters.formatForVerify, subresourceRange)); const VkImageMemoryBarrier refDstInitImageBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, refDstImage->get(), subresourceRange); const VkBufferCreateInfo refDstBufferInfo (makeBufferCreateInfo(dstBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)); const MovePtr refDstBuffer = MovePtr(new Buffer(vk, device, allocator, refDstBufferInfo, MemoryRequirement::HostVisible)); const VkImageCreateFlags resDstImageCreateFlags = 0; const VkImageUsageFlags resDstImageUsageFlags = VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; const VkImageCreateInfo resDstImageCreateInfo = makeCreateImageInfo(m_parameters.formatForVerify, m_parameters.imageType, mipmapDims, resDstImageUsageFlags, &resDstImageCreateFlags, SINGLE_LEVEL, SINGLE_LAYER); const MovePtr resDstImage (new Image(vk, device, allocator, resDstImageCreateInfo, MemoryRequirement::Any)); const Move resDstImageView (makeImageView(vk, device, resDstImage->get(), mapImageViewType(m_parameters.imageType), m_parameters.formatForVerify, subresourceRange)); const VkImageMemoryBarrier resDstInitImageBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, resDstImage->get(), subresourceRange); const VkBufferCreateInfo resDstBufferInfo (makeBufferCreateInfo(dstBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT)); const MovePtr resDstBuffer = MovePtr(new Buffer(vk, device, allocator, resDstBufferInfo, MemoryRequirement::HostVisible)); const Unique vertShaderModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0)); const Unique fragShaderModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag_verify"), 0)); const Unique renderPass (vk::makeRenderPass(vk, device)); const Move descriptorSetLayout (DescriptorSetLayoutBuilder() .addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT) .addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT) .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT) .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT) .build(vk, device)); const Move descriptorPool (DescriptorPoolBuilder() .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); const Move descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); const VkSamplerCreateInfo refSrcSamplerInfo (makeSamplerCreateInfo()); const Move refSrcSampler = vk::createSampler(vk, device, &refSrcSamplerInfo); const VkSamplerCreateInfo resSrcSamplerInfo (makeSamplerCreateInfo()); const Move resSrcSampler = vk::createSampler(vk, device, &resSrcSamplerInfo); const VkDescriptorImageInfo descriptorRefSrcImage (makeDescriptorImageInfo(*refSrcSampler, *refSrcImageView, layoutShaderReadOnly ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL)); const VkDescriptorImageInfo descriptorResSrcImage (makeDescriptorImageInfo(*resSrcSampler, *resSrcImageView, layoutShaderReadOnly ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL)); const VkDescriptorImageInfo descriptorRefDstImage (makeDescriptorImageInfo(DE_NULL, *refDstImageView, VK_IMAGE_LAYOUT_GENERAL)); const VkDescriptorImageInfo descriptorResDstImage (makeDescriptorImageInfo(DE_NULL, *resDstImageView, VK_IMAGE_LAYOUT_GENERAL)); const VkExtent2D renderSize (makeExtent2D(mipmapDims.x(), mipmapDims.y())); const Unique pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout)); const Unique pipeline (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertShaderModule, *fragShaderModule, renderSize, 0u)); const Unique cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT, queueFamilyIndex)); const Unique cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); const VkBufferImageCopy copyBufferToImageRegion = makeBufferImageCopy(mipmapDimsBlocked.x(), mipmapDimsBlocked.y(), 0u, 0u, mipmapDimsBlocked.x(), mipmapDimsBlocked.y()); const VkBufferImageCopy copyRegion = makeBufferImageCopy(mipmapDims.x(), mipmapDims.y(), 0u, 0u); const VkBufferMemoryBarrier refSrcCopyBufferBarrierPre = makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, refSrcImageBuffer->get(), 0ull, refCompressedData.size()); const VkImageMemoryBarrier refSrcCopyImageBarrierPre = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, refSrcImage->get(), subresourceRange); const VkImageMemoryBarrier refSrcCopyImageBarrierPost = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, layoutShaderReadOnly ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL, refSrcImage->get(), subresourceRange); const VkImageMemoryBarrier resCompressedImageBarrier = makeImageMemoryBarrier(0, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, layoutShaderReadOnly ? VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL : VK_IMAGE_LAYOUT_GENERAL, resCompressedImage->get(), resSubresourceRange); const Move framebuffer (makeFramebuffer(vk, device, *renderPass, 0, DE_NULL, renderSize.width, renderSize.height, getLayerCount())); // Upload source image data { const Allocation& refSrcImageBufferAlloc = refSrcImageBuffer->getAllocation(); deMemcpy(refSrcImageBufferAlloc.getHostPtr(), &refCompressedData[0], refCompressedData.size()); flushAlloc(vk, device, refSrcImageBufferAlloc); } beginCommandBuffer(vk, *cmdBuffer); vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); // Copy buffer to image vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1u, &refSrcCopyBufferBarrierPre, 1u, &refSrcCopyImageBarrierPre); vk.cmdCopyBufferToImage(*cmdBuffer, refSrcImageBuffer->get(), refSrcImage->get(), VK_IMAGE_LAYOUT_GENERAL, 1u, ©BufferToImageRegion); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, DE_NULL, 1u, &refSrcCopyImageBarrierPost); // Make reference and result images readable vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0u, DE_NULL, 1u, &refDstInitImageBarrier); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0u, DE_NULL, 1u, &resDstInitImageBarrier); { vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0u, DE_NULL, 1u, &resCompressedImageBarrier); } beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderSize); { DescriptorSetUpdateBuilder() .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorRefSrcImage) .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorResSrcImage) .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(2u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorRefDstImage) .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(3u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorResDstImage) .update(vk, device); vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &m_vertexBuffer->get(), &m_vertexBufferOffset); vk.cmdDraw(*cmdBuffer, m_vertexCount, 1, 0, 0); } endRenderPass(vk, *cmdBuffer); // Decompress reference image { const VkImageMemoryBarrier refDstImageBarrier = makeImageMemoryBarrier( VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, refDstImage->get(), subresourceRange); const VkBufferMemoryBarrier refDstBufferBarrier = makeBufferMemoryBarrier( VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, refDstBuffer->get(), 0ull, dstBufferSize); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &refDstImageBarrier); vk.cmdCopyImageToBuffer(*cmdBuffer, refDstImage->get(), VK_IMAGE_LAYOUT_GENERAL, refDstBuffer->get(), 1u, ©Region); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &refDstBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); } // Decompress result image { const VkImageMemoryBarrier resDstImageBarrier = makeImageMemoryBarrier( VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, resDstImage->get(), subresourceRange); const VkBufferMemoryBarrier resDstBufferBarrier = makeBufferMemoryBarrier( VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, resDstBuffer->get(), 0ull, dstBufferSize); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &resDstImageBarrier); vk.cmdCopyImageToBuffer(*cmdBuffer, resDstImage->get(), VK_IMAGE_LAYOUT_GENERAL, resDstBuffer->get(), 1u, ©Region); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &resDstBufferBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL); } endCommandBuffer(vk, *cmdBuffer); submitCommandsAndWait(vk, device, queue, *cmdBuffer); // Compare decompressed pixel data in reference and result images { const Allocation& refDstBufferAlloc = refDstBuffer->getAllocation(); invalidateAlloc(vk, device, refDstBufferAlloc); const Allocation& resDstBufferAlloc = resDstBuffer->getAllocation(); invalidateAlloc(vk, device, resDstBufferAlloc); BinaryCompareMode compareMode = (m_parameters.formatIsASTC) ?(COMPARE_MODE_ALLOW_ASTC_ERROR_COLOUR_WARNING) :(COMPARE_MODE_NORMAL); BinaryCompareResult res = BinaryCompare(refDstBufferAlloc.getHostPtr(), resDstBufferAlloc.getHostPtr(), dstBufferSize, m_parameters.formatForVerify, compareMode); if (res == COMPARE_RESULT_FAILED) { // Do fuzzy to log error mask invalidateAlloc(vk, device, resDstBufferAlloc); invalidateAlloc(vk, device, refDstBufferAlloc); tcu::ConstPixelBufferAccess resPixels (mapVkFormat(m_parameters.formatForVerify), renderSize.width, renderSize.height, 1u, resDstBufferAlloc.getHostPtr()); tcu::ConstPixelBufferAccess refPixels (mapVkFormat(m_parameters.formatForVerify), renderSize.width, renderSize.height, 1u, refDstBufferAlloc.getHostPtr()); string comment = string("Image Comparison (level=") + de::toString(level) + string(", layer=") + de::toString(layer) + string(")"); if (isWriteToCompressedOperation()) tcu::fuzzyCompare(m_context.getTestContext().getLog(), "ImageComparison", comment.c_str(), refPixels, resPixels, 0.001f, tcu::COMPARE_LOG_EVERYTHING); else tcu::fuzzyCompare(m_context.getTestContext().getLog(), "ImageComparison", comment.c_str(), resPixels, refPixels, 0.001f, tcu::COMPARE_LOG_EVERYTHING); return false; } else if (res == COMPARE_RESULT_ASTC_QUALITY_WARNING) { m_bASTCErrorColourMismatch = true; } } return true; } class GraphicsTextureTestInstance : public GraphicsAttachmentsTestInstance { public: GraphicsTextureTestInstance (Context& context, const TestParameters& parameters); protected: virtual bool isWriteToCompressedOperation (); virtual void transcodeRead (); virtual void transcodeWrite (); }; GraphicsTextureTestInstance::GraphicsTextureTestInstance (Context& context, const TestParameters& parameters) : GraphicsAttachmentsTestInstance(context, parameters) { } bool GraphicsTextureTestInstance::isWriteToCompressedOperation () { return (m_parameters.operation == OPERATION_TEXTURE_WRITE); } void GraphicsTextureTestInstance::transcodeRead () { const DeviceInterface& vk = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); const VkQueue queue = m_context.getUniversalQueue(); Allocator& allocator = m_context.getDefaultAllocator(); const VkImageCreateFlags* imgCreateFlagsOverride = DE_NULL; const VkImageCreateInfo srcImageCreateInfo = makeCreateImageInfo(m_srcFormat, m_parameters.imageType, m_srcImageResolutions[0], m_srcImageUsageFlags, imgCreateFlagsOverride, getLevelCount(), getLayerCount()); MovePtr srcImage (new Image(vk, device, allocator, srcImageCreateInfo, MemoryRequirement::Any)); const Unique vertShaderModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0)); const Unique fragShaderModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0)); const Unique renderPass (vk::makeRenderPass(vk, device)); const Move descriptorSetLayout (DescriptorSetLayoutBuilder() .addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT) .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT) .build(vk, device)); const Move descriptorPool (DescriptorPoolBuilder() .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); const Move descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); const VkExtent2D renderSizeDummy (makeExtent2D(1u, 1u)); const Unique pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout)); const Unique pipeline (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertShaderModule, *fragShaderModule, renderSizeDummy, 0u, true)); const Unique cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); const Unique cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); for (deUint32 levelNdx = 0; levelNdx < getLevelCount(); ++levelNdx) { const UVec3& uncompressedImageRes = m_uncompressedImageResVec[levelNdx]; const UVec3& srcImageResolution = m_srcImageResolutions[levelNdx]; const UVec3& dstImageResolution = m_dstImageResolutions[levelNdx]; const size_t srcImageSizeInBytes = m_srcData[levelNdx][0]->size(); const size_t dstImageSizeInBytes = m_dstData[levelNdx][0]->size(); const UVec3 srcImageResBlocked = getCompressedImageResolutionBlockCeil(m_parameters.formatCompressed, srcImageResolution); const VkImageCreateInfo dstImageCreateInfo = makeCreateImageInfo(m_dstFormat, m_parameters.imageType, dstImageResolution, m_dstImageUsageFlags, imgCreateFlagsOverride, SINGLE_LEVEL, SINGLE_LAYER); const VkBufferCreateInfo srcImageBufferInfo = makeBufferCreateInfo(srcImageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); const MovePtr srcImageBuffer = MovePtr(new Buffer(vk, device, allocator, srcImageBufferInfo, MemoryRequirement::HostVisible)); const VkBufferCreateInfo dstImageBufferInfo = makeBufferCreateInfo(dstImageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT); MovePtr dstImageBuffer = MovePtr(new Buffer(vk, device, allocator, dstImageBufferInfo, MemoryRequirement::HostVisible)); const VkExtent2D renderSize (makeExtent2D(uncompressedImageRes.x(), uncompressedImageRes.y())); const VkViewport viewport = makeViewport(renderSize); const VkRect2D scissor = makeRect2D(renderSize); for (deUint32 layerNdx = 0; layerNdx < getLayerCount(); ++layerNdx) { const VkImageSubresourceRange srcSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, levelNdx, SINGLE_LEVEL, layerNdx, SINGLE_LAYER); const VkImageSubresourceRange dstSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, SINGLE_LEVEL, 0u, SINGLE_LAYER); Move srcImageView (makeImageView(vk, device, srcImage->get(), mapImageViewType(m_parameters.imageType), m_parameters.formatUncompressed, srcSubresourceRange, m_srcImageViewUsageKHR)); de::MovePtr dstImage (new Image(vk, device, allocator, dstImageCreateInfo, MemoryRequirement::Any)); Move dstImageView (makeImageView(vk, device, dstImage->get(), mapImageViewType(m_parameters.imageType), m_parameters.formatUncompressed, dstSubresourceRange, m_dstImageViewUsageKHR)); const VkSamplerCreateInfo srcSamplerInfo (makeSamplerCreateInfo()); const Move srcSampler = vk::createSampler(vk, device, &srcSamplerInfo); const VkDescriptorImageInfo descriptorSrcImage (makeDescriptorImageInfo(*srcSampler, *srcImageView, VK_IMAGE_LAYOUT_GENERAL)); const VkDescriptorImageInfo descriptorDstImage (makeDescriptorImageInfo(DE_NULL, *dstImageView, VK_IMAGE_LAYOUT_GENERAL)); const VkBufferImageCopy srcCopyRegion = makeBufferImageCopy(srcImageResolution.x(), srcImageResolution.y(), levelNdx, layerNdx, srcImageResBlocked.x(), srcImageResBlocked.y()); const VkBufferMemoryBarrier srcCopyBufferBarrierPre = makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, srcImageBuffer->get(), 0ull, srcImageSizeInBytes); const VkImageMemoryBarrier srcCopyImageBarrierPre = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, srcImage->get(), srcSubresourceRange); const VkImageMemoryBarrier srcCopyImageBarrierPost = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, srcImage->get(), srcSubresourceRange); const VkBufferImageCopy dstCopyRegion = makeBufferImageCopy(dstImageResolution.x(), dstImageResolution.y()); const VkImageMemoryBarrier dstInitImageBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, dstImage->get(), dstSubresourceRange); const VkExtent2D framebufferSize (makeExtent2D(dstImageResolution[0], dstImageResolution[1])); const Move framebuffer (makeFramebuffer(vk, device, *renderPass, 0, DE_NULL, framebufferSize.width, framebufferSize.height, SINGLE_LAYER)); // Upload source image data const Allocation& alloc = srcImageBuffer->getAllocation(); deMemcpy(alloc.getHostPtr(), &m_srcData[levelNdx][layerNdx]->at(0), srcImageSizeInBytes); flushAlloc(vk, device, alloc); beginCommandBuffer(vk, *cmdBuffer); vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); // Copy buffer to image vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1u, &srcCopyBufferBarrierPre, 1u, &srcCopyImageBarrierPre); vk.cmdCopyBufferToImage(*cmdBuffer, srcImageBuffer->get(), srcImage->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &srcCopyRegion); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0u, DE_NULL, 1u, &srcCopyImageBarrierPost); // Define destination image layout vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0u, DE_NULL, 1u, &dstInitImageBarrier); beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderSize); DescriptorSetUpdateBuilder() .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorSrcImage) .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImage) .update(vk, device); vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &m_vertexBuffer->get(), &m_vertexBufferOffset); vk.cmdSetViewport(*cmdBuffer, 0u, 1u, &viewport); vk.cmdSetScissor(*cmdBuffer, 0u, 1u, &scissor); vk.cmdDraw(*cmdBuffer, (deUint32)m_vertexCount, 1, 0, 0); endRenderPass(vk, *cmdBuffer); const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier( VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, dstImage->get(), dstSubresourceRange); const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier( VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, dstImageBuffer->get(), 0ull, dstImageSizeInBytes); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &prepareForTransferBarrier); vk.cmdCopyImageToBuffer(*cmdBuffer, dstImage->get(), VK_IMAGE_LAYOUT_GENERAL, dstImageBuffer->get(), 1u, &dstCopyRegion); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, ©Barrier, 0, (const VkImageMemoryBarrier*)DE_NULL); endCommandBuffer(vk, *cmdBuffer); submitCommandsAndWait(vk, device, queue, *cmdBuffer); const Allocation& dstImageBufferAlloc = dstImageBuffer->getAllocation(); invalidateAlloc(vk, device, dstImageBufferAlloc); deMemcpy(&m_dstData[levelNdx][layerNdx]->at(0), dstImageBufferAlloc.getHostPtr(), dstImageSizeInBytes); } } m_compressedImage = srcImage; } void GraphicsTextureTestInstance::transcodeWrite () { const DeviceInterface& vk = m_context.getDeviceInterface(); const VkDevice device = m_context.getDevice(); const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex(); const VkQueue queue = m_context.getUniversalQueue(); Allocator& allocator = m_context.getDefaultAllocator(); const VkImageCreateFlags* imgCreateFlagsOverride = DE_NULL; const VkImageCreateInfo dstImageCreateInfo = makeCreateImageInfo(m_dstFormat, m_parameters.imageType, m_dstImageResolutions[0], m_dstImageUsageFlags, imgCreateFlagsOverride, getLevelCount(), getLayerCount()); MovePtr dstImage (new Image(vk, device, allocator, dstImageCreateInfo, MemoryRequirement::Any)); const Unique vertShaderModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0)); const Unique fragShaderModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0)); const Unique renderPass (vk::makeRenderPass(vk, device)); const Move descriptorSetLayout (DescriptorSetLayoutBuilder() .addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT) .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT) .build(vk, device)); const Move descriptorPool (DescriptorPoolBuilder() .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u)); const Move descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout)); const VkExtent2D renderSizeDummy (makeExtent2D(1u, 1u)); const Unique pipelineLayout (makePipelineLayout(vk, device, *descriptorSetLayout)); const Unique pipeline (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertShaderModule, *fragShaderModule, renderSizeDummy, 0u, true)); const Unique cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex)); const Unique cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY)); for (deUint32 levelNdx = 0; levelNdx < getLevelCount(); ++levelNdx) { const UVec3& uncompressedImageRes = m_uncompressedImageResVec[levelNdx]; const UVec3& srcImageResolution = m_srcImageResolutions[levelNdx]; const UVec3& dstImageResolution = m_dstImageResolutions[levelNdx]; const size_t srcImageSizeInBytes = m_srcData[levelNdx][0]->size(); const size_t dstImageSizeInBytes = m_dstData[levelNdx][0]->size(); const UVec3 dstImageResBlocked = getCompressedImageResolutionBlockCeil(m_parameters.formatCompressed, dstImageResolution); const VkImageCreateInfo srcImageCreateInfo = makeCreateImageInfo(m_srcFormat, m_parameters.imageType, srcImageResolution, m_srcImageUsageFlags, imgCreateFlagsOverride, SINGLE_LEVEL, SINGLE_LAYER); const VkExtent2D renderSize (makeExtent2D(uncompressedImageRes.x(), uncompressedImageRes.y())); const VkViewport viewport = makeViewport(renderSize); const VkRect2D scissor = makeRect2D(renderSize); for (deUint32 layerNdx = 0; layerNdx < getLayerCount(); ++layerNdx) { const VkBufferCreateInfo srcImageBufferInfo = makeBufferCreateInfo(srcImageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_SRC_BIT); const MovePtr srcImageBuffer = MovePtr(new Buffer(vk, device, allocator, srcImageBufferInfo, MemoryRequirement::HostVisible)); const VkBufferCreateInfo dstImageBufferInfo = makeBufferCreateInfo(dstImageSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT); MovePtr dstImageBuffer = MovePtr(new Buffer(vk, device, allocator, dstImageBufferInfo, MemoryRequirement::HostVisible)); const VkImageSubresourceRange srcSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, SINGLE_LEVEL, 0u, SINGLE_LAYER); const VkImageSubresourceRange dstSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, levelNdx, SINGLE_LEVEL, layerNdx, SINGLE_LAYER); Move dstImageView (makeImageView(vk, device, dstImage->get(), mapImageViewType(m_parameters.imageType), m_parameters.formatUncompressed, dstSubresourceRange, m_dstImageViewUsageKHR)); de::MovePtr srcImage (new Image(vk, device, allocator, srcImageCreateInfo, MemoryRequirement::Any)); Move srcImageView (makeImageView(vk, device, srcImage->get(), mapImageViewType(m_parameters.imageType), m_parameters.formatUncompressed, srcSubresourceRange, m_srcImageViewUsageKHR)); const VkSamplerCreateInfo srcSamplerInfo (makeSamplerCreateInfo()); const Move srcSampler = vk::createSampler(vk, device, &srcSamplerInfo); const VkDescriptorImageInfo descriptorSrcImage (makeDescriptorImageInfo(*srcSampler, *srcImageView, VK_IMAGE_LAYOUT_GENERAL)); const VkDescriptorImageInfo descriptorDstImage (makeDescriptorImageInfo(DE_NULL, *dstImageView, VK_IMAGE_LAYOUT_GENERAL)); const VkBufferImageCopy srcCopyRegion = makeBufferImageCopy(srcImageResolution.x(), srcImageResolution.y(), 0u, 0u); const VkBufferMemoryBarrier srcCopyBufferBarrierPre = makeBufferMemoryBarrier(VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, srcImageBuffer->get(), 0ull, srcImageSizeInBytes); const VkImageMemoryBarrier srcCopyImageBarrierPre = makeImageMemoryBarrier(0u, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, srcImage->get(), srcSubresourceRange); const VkImageMemoryBarrier srcCopyImageBarrierPost = makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_GENERAL, srcImage->get(), srcSubresourceRange); const VkBufferImageCopy dstCopyRegion = makeBufferImageCopy(dstImageResolution.x(), dstImageResolution.y(), levelNdx, layerNdx, dstImageResBlocked.x(), dstImageResBlocked.y()); const VkImageMemoryBarrier dstInitImageBarrier = makeImageMemoryBarrier(0u, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, dstImage->get(), dstSubresourceRange); const VkExtent2D framebufferSize (makeExtent2D(dstImageResolution[0], dstImageResolution[1])); const Move framebuffer (makeFramebuffer(vk, device, *renderPass, 0, DE_NULL, framebufferSize.width, framebufferSize.height, SINGLE_LAYER)); // Upload source image data const Allocation& alloc = srcImageBuffer->getAllocation(); deMemcpy(alloc.getHostPtr(), &m_srcData[levelNdx][layerNdx]->at(0), srcImageSizeInBytes); flushAlloc(vk, device, alloc); beginCommandBuffer(vk, *cmdBuffer); vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline); // Copy buffer to image vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1u, &srcCopyBufferBarrierPre, 1u, &srcCopyImageBarrierPre); vk.cmdCopyBufferToImage(*cmdBuffer, srcImageBuffer->get(), srcImage->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &srcCopyRegion); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0u, DE_NULL, 1u, &srcCopyImageBarrierPost); // Define destination image layout vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0u, DE_NULL, 1u, &dstInitImageBarrier); beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderSize); DescriptorSetUpdateBuilder() .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorSrcImage) .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorDstImage) .update(vk, device); vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL); vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &m_vertexBuffer->get(), &m_vertexBufferOffset); vk.cmdSetViewport(*cmdBuffer, 0u, 1u, &viewport); vk.cmdSetScissor(*cmdBuffer, 0u, 1u, &scissor); vk.cmdDraw(*cmdBuffer, (deUint32)m_vertexCount, 1, 0, 0); endRenderPass(vk, *cmdBuffer); const VkImageMemoryBarrier prepareForTransferBarrier = makeImageMemoryBarrier( VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_GENERAL, dstImage->get(), dstSubresourceRange); const VkBufferMemoryBarrier copyBarrier = makeBufferMemoryBarrier( VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, dstImageBuffer->get(), 0ull, dstImageSizeInBytes); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &prepareForTransferBarrier); vk.cmdCopyImageToBuffer(*cmdBuffer, dstImage->get(), VK_IMAGE_LAYOUT_GENERAL, dstImageBuffer->get(), 1u, &dstCopyRegion); vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, ©Barrier, 0, (const VkImageMemoryBarrier*)DE_NULL); endCommandBuffer(vk, *cmdBuffer); submitCommandsAndWait(vk, device, queue, *cmdBuffer); const Allocation& dstImageBufferAlloc = dstImageBuffer->getAllocation(); invalidateAlloc(vk, device, dstImageBufferAlloc); deMemcpy(&m_dstData[levelNdx][layerNdx]->at(0), dstImageBufferAlloc.getHostPtr(), dstImageSizeInBytes); } } m_compressedImage = dstImage; } class TexelViewCompatibleCase : public TestCase { public: TexelViewCompatibleCase (TestContext& testCtx, const std::string& name, const std::string& desc, const TestParameters& parameters); void initPrograms (SourceCollections& programCollection) const; TestInstance* createInstance (Context& context) const; virtual void checkSupport (Context& context) const; protected: const TestParameters m_parameters; }; TexelViewCompatibleCase::TexelViewCompatibleCase (TestContext& testCtx, const std::string& name, const std::string& desc, const TestParameters& parameters) : TestCase (testCtx, name, desc) , m_parameters (parameters) { } void TexelViewCompatibleCase::initPrograms (vk::SourceCollections& programCollection) const { DE_ASSERT(m_parameters.size.x() > 0); DE_ASSERT(m_parameters.size.y() > 0); const unsigned int imageTypeIndex = (m_parameters.imageType == IMAGE_TYPE_2D) + (m_parameters.imageType == IMAGE_TYPE_3D) * 2; switch (m_parameters.shader) { case SHADER_TYPE_COMPUTE: { const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_parameters.formatUncompressed), m_parameters.imageType); const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_parameters.formatUncompressed)); std::ostringstream src; std::ostringstream src_decompress; src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n" << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n\n"; src_decompress << src.str(); switch(m_parameters.operation) { case OPERATION_IMAGE_LOAD: { const char* posDefinitions[3] = { // IMAGE_TYPE_1D " highp int pos = int(gl_GlobalInvocationID.x);\n", // IMAGE_TYPE_2D " ivec2 pos = ivec2(gl_GlobalInvocationID.xy);\n", // IMAGE_TYPE_3D " ivec3 pos = ivec3(gl_GlobalInvocationID);\n", }; src << "layout (binding = 0, "< 0u); DE_ASSERT(getLayerSize(m_parameters.imageType, m_parameters.size).y() > 0u); switch (m_parameters.shader) { case SHADER_TYPE_COMPUTE: { switch (m_parameters.operation) { case OPERATION_IMAGE_LOAD: case OPERATION_TEXEL_FETCH: case OPERATION_TEXTURE: return new BasicComputeTestInstance(context, m_parameters); case OPERATION_IMAGE_STORE: return new ImageStoreComputeTestInstance(context, m_parameters); default: TCU_THROW(InternalError, "Impossible"); } } case SHADER_TYPE_FRAGMENT: { switch (m_parameters.operation) { case OPERATION_ATTACHMENT_READ: case OPERATION_ATTACHMENT_WRITE: return new GraphicsAttachmentsTestInstance(context, m_parameters); case OPERATION_TEXTURE_READ: case OPERATION_TEXTURE_WRITE: return new GraphicsTextureTestInstance(context, m_parameters); default: TCU_THROW(InternalError, "Impossible"); } } default: TCU_THROW(InternalError, "Impossible"); } } } // anonymous ns static tcu::UVec3 getUnniceResolution (const VkFormat format, const deUint32 layers) { const deUint32 unniceMipmapTextureSize[] = { 1, 1, 1, 8, 22, 48, 117, 275, 604, 208, 611, 274, 1211 }; const deUint32 baseTextureWidth = unniceMipmapTextureSize[getBlockWidth(format)]; const deUint32 baseTextureHeight = unniceMipmapTextureSize[getBlockHeight(format)]; const deUint32 baseTextureWidthLevels = deLog2Floor32(baseTextureWidth); const deUint32 baseTextureHeightLevels = deLog2Floor32(baseTextureHeight); const deUint32 widthMultiplier = (baseTextureHeightLevels > baseTextureWidthLevels) ? 1u << (baseTextureHeightLevels - baseTextureWidthLevels) : 1u; const deUint32 heightMultiplier = (baseTextureWidthLevels > baseTextureHeightLevels) ? 1u << (baseTextureWidthLevels - baseTextureHeightLevels) : 1u; const deUint32 width = baseTextureWidth * widthMultiplier; const deUint32 height = baseTextureHeight * heightMultiplier; // Number of levels should be same on both axises DE_ASSERT(deLog2Floor32(width) == deLog2Floor32(height)); return tcu::UVec3(width, height, layers); } tcu::TestCaseGroup* createImageCompressionTranscodingTests (tcu::TestContext& testCtx) { struct FormatsArray { const VkFormat* formats; deUint32 count; }; const bool mipmapness[] = { false, true, }; const std::string pipelineName[SHADER_TYPE_LAST] = { "compute", "graphic", }; const std::string mipmanpnessName[DE_LENGTH_OF_ARRAY(mipmapness)] = { "basic", "extended", }; const std::string operationName[OPERATION_LAST] = { "image_load", "texel_fetch", "texture", "image_store", "attachment_read", "attachment_write", "texture_read", "texture_write", }; struct ImageTypeName { ImageType type; std::string name; }; ImageTypeName imageTypes[] = { { IMAGE_TYPE_1D, "1d_image" }, { IMAGE_TYPE_2D, "2d_image" }, { IMAGE_TYPE_3D, "3d_image" }, }; const VkImageUsageFlags baseImageUsageFlagSet = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; const VkImageUsageFlags compressedImageUsageFlags[OPERATION_LAST] = { baseImageUsageFlagSet | static_cast(VK_IMAGE_USAGE_STORAGE_BIT), // "image_load" baseImageUsageFlagSet | static_cast(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT), // "texel_fetch" baseImageUsageFlagSet | static_cast(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT), // "texture" baseImageUsageFlagSet | static_cast(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT), // "image_store" baseImageUsageFlagSet | static_cast(VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT), // "attachment_read" baseImageUsageFlagSet | static_cast(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT), // "attachment_write" baseImageUsageFlagSet | static_cast(VK_IMAGE_USAGE_SAMPLED_BIT), // "texture_read" baseImageUsageFlagSet | static_cast(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT), // "texture_write" }; const VkImageUsageFlags compressedImageViewUsageFlags[OPERATION_LAST] = { compressedImageUsageFlags[0], //"image_load" compressedImageUsageFlags[1], //"texel_fetch" compressedImageUsageFlags[2], //"texture" compressedImageUsageFlags[3], //"image_store" compressedImageUsageFlags[4], //"attachment_read" compressedImageUsageFlags[5] | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, //"attachment_write" compressedImageUsageFlags[6], //"texture_read" compressedImageUsageFlags[7], //"texture_write" }; const VkImageUsageFlags uncompressedImageUsageFlags[OPERATION_LAST] = { baseImageUsageFlagSet | static_cast(VK_IMAGE_USAGE_STORAGE_BIT), //"image_load" baseImageUsageFlagSet | static_cast(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT), //"texel_fetch" baseImageUsageFlagSet | static_cast(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT), //"texture" baseImageUsageFlagSet | static_cast(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT), //"image_store" baseImageUsageFlagSet | static_cast(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT), //"attachment_read" baseImageUsageFlagSet | static_cast(VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT), //"attachment_write" baseImageUsageFlagSet | static_cast(VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT), //"texture_read" baseImageUsageFlagSet | static_cast(VK_IMAGE_USAGE_SAMPLED_BIT), //"texture_write" }; const VkFormat compressedFormats64bit[] = { VK_FORMAT_BC1_RGB_UNORM_BLOCK, VK_FORMAT_BC1_RGB_SRGB_BLOCK, VK_FORMAT_BC1_RGBA_UNORM_BLOCK, VK_FORMAT_BC1_RGBA_SRGB_BLOCK, VK_FORMAT_BC4_UNORM_BLOCK, VK_FORMAT_BC4_SNORM_BLOCK, VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, VK_FORMAT_EAC_R11_UNORM_BLOCK, VK_FORMAT_EAC_R11_SNORM_BLOCK, }; const VkFormat compressedFormats128bit[] = { VK_FORMAT_BC2_UNORM_BLOCK, VK_FORMAT_BC2_SRGB_BLOCK, VK_FORMAT_BC3_UNORM_BLOCK, VK_FORMAT_BC3_SRGB_BLOCK, VK_FORMAT_BC5_UNORM_BLOCK, VK_FORMAT_BC5_SNORM_BLOCK, VK_FORMAT_BC6H_UFLOAT_BLOCK, VK_FORMAT_BC6H_SFLOAT_BLOCK, VK_FORMAT_BC7_UNORM_BLOCK, VK_FORMAT_BC7_SRGB_BLOCK, VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, VK_FORMAT_EAC_R11G11_UNORM_BLOCK, VK_FORMAT_EAC_R11G11_SNORM_BLOCK, VK_FORMAT_ASTC_4x4_UNORM_BLOCK, VK_FORMAT_ASTC_4x4_SRGB_BLOCK, VK_FORMAT_ASTC_5x4_UNORM_BLOCK, VK_FORMAT_ASTC_5x4_SRGB_BLOCK, VK_FORMAT_ASTC_5x5_UNORM_BLOCK, VK_FORMAT_ASTC_5x5_SRGB_BLOCK, VK_FORMAT_ASTC_6x5_UNORM_BLOCK, VK_FORMAT_ASTC_6x5_SRGB_BLOCK, VK_FORMAT_ASTC_6x6_UNORM_BLOCK, VK_FORMAT_ASTC_6x6_SRGB_BLOCK, VK_FORMAT_ASTC_8x5_UNORM_BLOCK, VK_FORMAT_ASTC_8x5_SRGB_BLOCK, VK_FORMAT_ASTC_8x6_UNORM_BLOCK, VK_FORMAT_ASTC_8x6_SRGB_BLOCK, VK_FORMAT_ASTC_8x8_UNORM_BLOCK, VK_FORMAT_ASTC_8x8_SRGB_BLOCK, VK_FORMAT_ASTC_10x5_UNORM_BLOCK, VK_FORMAT_ASTC_10x5_SRGB_BLOCK, VK_FORMAT_ASTC_10x6_UNORM_BLOCK, VK_FORMAT_ASTC_10x6_SRGB_BLOCK, VK_FORMAT_ASTC_10x8_UNORM_BLOCK, VK_FORMAT_ASTC_10x8_SRGB_BLOCK, VK_FORMAT_ASTC_10x10_UNORM_BLOCK, VK_FORMAT_ASTC_10x10_SRGB_BLOCK, VK_FORMAT_ASTC_12x10_UNORM_BLOCK, VK_FORMAT_ASTC_12x10_SRGB_BLOCK, VK_FORMAT_ASTC_12x12_UNORM_BLOCK, VK_FORMAT_ASTC_12x12_SRGB_BLOCK, }; const VkFormat uncompressedFormats64bit[] = { VK_FORMAT_R16G16B16A16_UNORM, VK_FORMAT_R16G16B16A16_SNORM, VK_FORMAT_R16G16B16A16_USCALED, VK_FORMAT_R16G16B16A16_SSCALED, VK_FORMAT_R16G16B16A16_UINT, VK_FORMAT_R16G16B16A16_SINT, //VK_FORMAT_R16G16B16A16_SFLOAT, removed as float views can't preserve NAN/INF/Denorm values VK_FORMAT_R32G32_UINT, VK_FORMAT_R32G32_SINT, //VK_FORMAT_R32G32_SFLOAT, removed as float views can't preserve NAN/INF/Denorm values //VK_FORMAT_R64_UINT, remove from the test it couldn't be used //VK_FORMAT_R64_SINT, remove from the test it couldn't be used //VK_FORMAT_R64_SFLOAT, remove from the test it couldn't be used }; const VkFormat uncompressedFormats128bit[] = { VK_FORMAT_R32G32B32A32_UINT, VK_FORMAT_R32G32B32A32_SINT, //VK_FORMAT_R32G32B32A32_SFLOAT, removed as float views can't preserve NAN/INF/Denorm values //VK_FORMAT_R64G64_UINT, remove from the test it couldn't be used //VK_FORMAT_R64G64_SINT, remove from the test it couldn't be used //VK_FORMAT_R64G64_SFLOAT, remove from the test it couldn't be used }; const FormatsArray formatsCompressedSets[] = { { compressedFormats64bit, DE_LENGTH_OF_ARRAY(compressedFormats64bit) }, { compressedFormats128bit, DE_LENGTH_OF_ARRAY(compressedFormats128bit) }, }; // Uncompressed formats - floating point formats should not be used in these // tests as they cannot be relied upon to preserve all possible values in the // underlying texture data. Refer to the note under the 'VkImageViewCreateInfo' // section of the specification. const FormatsArray formatsUncompressedSets[] = { { uncompressedFormats64bit, DE_LENGTH_OF_ARRAY(uncompressedFormats64bit) }, { uncompressedFormats128bit, DE_LENGTH_OF_ARRAY(uncompressedFormats128bit) }, }; DE_ASSERT(DE_LENGTH_OF_ARRAY(formatsCompressedSets) == DE_LENGTH_OF_ARRAY(formatsUncompressedSets)); MovePtr texelViewCompatibleTests (new tcu::TestCaseGroup(testCtx, "texel_view_compatible", "Texel view compatible cases")); for (int shaderType = SHADER_TYPE_COMPUTE; shaderType < SHADER_TYPE_LAST; ++shaderType) { MovePtr pipelineTypeGroup (new tcu::TestCaseGroup(testCtx, pipelineName[shaderType].c_str(), "")); for (int mipmapTestNdx = 0; mipmapTestNdx < DE_LENGTH_OF_ARRAY(mipmapness); mipmapTestNdx++) { const bool mipmapTest = mipmapness[mipmapTestNdx]; MovePtr mipmapTypeGroup (new tcu::TestCaseGroup(testCtx, mipmanpnessName[mipmapTestNdx].c_str(), "")); for (int imageTypeNdx = 0; imageTypeNdx < DE_LENGTH_OF_ARRAY(imageTypes); imageTypeNdx++) { MovePtr imageTypeGroup (new tcu::TestCaseGroup(testCtx, imageTypes[imageTypeNdx].name.c_str(), "")); ImageType imageType = imageTypes[imageTypeNdx].type; for (int operationNdx = OPERATION_IMAGE_LOAD; operationNdx < OPERATION_LAST; ++operationNdx) { if (shaderType != SHADER_TYPE_FRAGMENT && deInRange32(operationNdx, OPERATION_ATTACHMENT_READ, OPERATION_TEXTURE_WRITE)) continue; if (shaderType != SHADER_TYPE_COMPUTE && deInRange32(operationNdx, OPERATION_IMAGE_LOAD, OPERATION_IMAGE_STORE)) continue; if (imageType == IMAGE_TYPE_3D && (operationNdx == OPERATION_ATTACHMENT_READ || operationNdx == OPERATION_ATTACHMENT_WRITE)) continue; MovePtr imageOperationGroup (new tcu::TestCaseGroup(testCtx, operationName[operationNdx].c_str(), "")); deUint32 depth = 1u + 2 * (imageType == IMAGE_TYPE_3D); deUint32 imageCount = 2u + (operationNdx == OPERATION_IMAGE_STORE); // Iterate through bitness groups (64 bit, 128 bit, etc) for (deUint32 formatBitnessGroup = 0; formatBitnessGroup < DE_LENGTH_OF_ARRAY(formatsCompressedSets); ++formatBitnessGroup) { for (deUint32 formatCompressedNdx = 0; formatCompressedNdx < formatsCompressedSets[formatBitnessGroup].count; ++formatCompressedNdx) { const VkFormat formatCompressed = formatsCompressedSets[formatBitnessGroup].formats[formatCompressedNdx]; const std::string compressedFormatGroupName = getFormatShortString(formatCompressed); MovePtr compressedFormatGroup (new tcu::TestCaseGroup(testCtx, compressedFormatGroupName.c_str(), "")); for (deUint32 formatUncompressedNdx = 0; formatUncompressedNdx < formatsUncompressedSets[formatBitnessGroup].count; ++formatUncompressedNdx) { const VkFormat formatUncompressed = formatsUncompressedSets[formatBitnessGroup].formats[formatUncompressedNdx]; const std::string uncompressedFormatGroupName = getFormatShortString(formatUncompressed); const TestParameters parameters = { static_cast(operationNdx), static_cast(shaderType), mipmapTest ? getUnniceResolution(formatCompressed, 1u) : UVec3(64u, 64u, depth), 1u + 2u * mipmapTest * (imageType != IMAGE_TYPE_3D), // 1 or 3 if mipmapTest is true but image is not 3d imageType, formatCompressed, formatUncompressed, imageCount, compressedImageUsageFlags[operationNdx], compressedImageViewUsageFlags[operationNdx], uncompressedImageUsageFlags[operationNdx], mipmapTest, VK_FORMAT_R8G8B8A8_UNORM, FormatIsASTC(formatCompressed) }; compressedFormatGroup->addChild(new TexelViewCompatibleCase(testCtx, uncompressedFormatGroupName, "", parameters)); } imageOperationGroup->addChild(compressedFormatGroup.release()); } } imageTypeGroup->addChild(imageOperationGroup.release()); } mipmapTypeGroup->addChild(imageTypeGroup.release()); } pipelineTypeGroup->addChild(mipmapTypeGroup.release()); } texelViewCompatibleTests->addChild(pipelineTypeGroup.release()); } return texelViewCompatibleTests.release(); } } // image } // vkt