Merge vk-gl-cts/vulkan-cts-1.2.7 into vk-gl-cts/vulkan-cts-1.2.8
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / image / vktImageLoadStoreTests.cpp
index 45abcda..af0661c 100644 (file)
@@ -51,6 +51,7 @@
 #include "tcuTextureUtil.hpp"
 #include "tcuFloat.hpp"
 #include "tcuStringTemplate.hpp"
+#include "tcuVectorUtil.hpp"
 
 #include <string>
 #include <vector>
@@ -179,8 +180,12 @@ bool comparePixelBuffers (tcu::TestLog&                                            log,
 
                        case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
                        {
+                               const tcu::UVec4 bitDepth = tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>() - 1u;
+                               // To avoid bit-shifting with negative value, which is undefined behaviour.
+                               const tcu::UVec4 fixedBitDepth = tcu::select(bitDepth, tcu::UVec4(0u, 0u, 0u, 0u), tcu::greaterThanEqual(bitDepth.cast<deInt32>(), tcu::IVec4(0, 0, 0, 0)));
+
                                // Allow error of minimum representable difference
-                               const tcu::Vec4 threshold (1.0f / ((tcu::UVec4(1u) << (tcu::getTextureFormatMantissaBitDepth(mapVkFormat(format)).cast<deUint32>() - 1u)) - 1u).cast<float>());
+                               const tcu::Vec4 threshold (1.0f / ((tcu::UVec4(1u) << fixedBitDepth) - 1u).cast<float>());
 
                                ok = tcu::floatThresholdCompare(log, comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, threshold, tcu::COMPARE_LOG_RESULT);
                                break;
@@ -479,10 +484,13 @@ StoreTest::StoreTest (tcu::TestContext&           testCtx,
 
 void StoreTest::checkSupport (Context& context) const
 {
-       const VkFormatProperties formatProperties (getPhysicalDeviceFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(), m_format));
+       const VkFormatProperties3KHR formatProperties (context.getFormatProperties(m_format));
 
-       if (!m_declareImageFormatInShader)
-               context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT);
+       if (!m_declareImageFormatInShader && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR))
+               TCU_THROW(NotSupportedError, "Format not supported for unformatted stores via storage buffer");
+
+       if (!m_declareImageFormatInShader && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT_KHR))
+               TCU_THROW(NotSupportedError, "Format not supported for unformatted stores via storage images");
 
        if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
                context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
@@ -563,7 +571,6 @@ void StoreTest::initPrograms (SourceCollections& programCollection) const
        const std::string texelCoordStr = (dimension == 1 ? "gx" : dimension == 2 ? "ivec2(gx, gy)" : dimension == 3 ? "ivec3(gx, gy, gz)" : "");
 
        const ImageType usedImageType = (m_singleLayerBind ? getImageTypeForSingleLayer(m_texture.type()) : m_texture.type());
-       const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format));
        const std::string imageTypeStr = getShaderImageType(mapVkFormat(m_format), usedImageType);
 
        std::ostringstream src;
@@ -571,7 +578,10 @@ void StoreTest::initPrograms (SourceCollections& programCollection) const
                << "\n"
                << "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n";
        if (m_declareImageFormatInShader)
+       {
+               const std::string formatQualifierStr = getShaderImageFormatQualifier(mapVkFormat(m_format));
                src << "layout (binding = 0, " << formatQualifierStr << ") writeonly uniform " << imageTypeStr << " u_image;\n";
+       }
        else
                src << "layout (binding = 0) writeonly uniform " << imageTypeStr << " u_image;\n";
 
@@ -1077,17 +1087,14 @@ LoadStoreTest::LoadStoreTest (tcu::TestContext&         testCtx,
 
 void LoadStoreTest::checkSupport (Context& context) const
 {
-       const vk::VkFormatProperties    formatProperties        (vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
-                                                                                                                                                                                          context.getPhysicalDevice(),
-                                                                                                                                                                                          m_format));
-       const vk::VkFormatProperties imageFormatProperties  (vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
-                                                                                                                                                                                          context.getPhysicalDevice(),
-                                                                                                                                                                                          m_imageFormat));
+       const VkFormatProperties3KHR formatProperties (context.getFormatProperties(m_format));
+       const VkFormatProperties3KHR imageFormatProperties (context.getFormatProperties(m_imageFormat));
+
        if (m_imageLoadStoreLodAMD)
                context.requireDeviceFunctionality("VK_AMD_shader_image_load_store_lod");
 
-       if (!m_bufferLoadUniform && !m_declareImageFormatInShader)
-               context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_STORAGE_IMAGE_READ_WITHOUT_FORMAT);
+       if (!m_bufferLoadUniform && !m_declareImageFormatInShader && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT_KHR))
+               TCU_THROW(NotSupportedError, "Format not supported for unformatted loads via storage images");
 
        if (m_texture.type() == IMAGE_TYPE_CUBE_ARRAY)
                context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_IMAGE_CUBE_ARRAY);
@@ -1104,13 +1111,11 @@ void LoadStoreTest::checkSupport (Context& context) const
        if ((m_texture.type() == IMAGE_TYPE_BUFFER) && !(imageFormatProperties.bufferFeatures))
                TCU_THROW(NotSupportedError, "Underlying format not supported at all for buffers");
 
-    if (formatHasThreeComponents(m_format))
+       if (formatHasThreeComponents(m_format))
        {
                // When the source buffer is three-component, the destination buffer is single-component.
                VkFormat dstFormat = getSingleComponentFormat(m_format);
-               const vk::VkFormatProperties    dstFormatProperties     (vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
-                                                                                                                                                                                                  context.getPhysicalDevice(),
-                                                                                                                                                                                                  dstFormat));
+               const VkFormatProperties3KHR dstFormatProperties (context.getFormatProperties(dstFormat));
 
                if (m_texture.type() == IMAGE_TYPE_BUFFER && !(dstFormatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
                        TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
@@ -1920,9 +1925,11 @@ class ImageExtendOperandTestInstance : public BaseTestInstance
 public:
                                                                        ImageExtendOperandTestInstance                  (Context&                               context,
                                                                                                                                                         const Texture&                 texture,
-                                                                                                                                                        const VkFormat                 format);
+                                                                                                                                                        const VkFormat                 readFormat,
+                                                                                                                                                        const VkFormat                 writeFormat,
+                                                                                                                                                        bool                                   relaxedPrecision);
 
-       virtual                                                 ~ImageExtendOperandTestInstance                 (void) {};
+       virtual                                                 ~ImageExtendOperandTestInstance                 (void) {}
 
 protected:
 
@@ -1956,12 +1963,18 @@ protected:
        Move<VkDescriptorSetLayout>             m_descriptorSetLayout;
        Move<VkDescriptorPool>                  m_descriptorPool;
        SharedVkDescriptorSet                   m_descriptorSet;
+
+       bool                                                    m_relaxedPrecision;
 };
 
 ImageExtendOperandTestInstance::ImageExtendOperandTestInstance (Context& context,
                                                                                                                                const Texture& texture,
-                                                                                                                               const VkFormat format)
-       : BaseTestInstance              (context, texture, format, true, true, false, false)
+                                                                                                                               const VkFormat readFormat,
+                                                                                                                               const VkFormat writeFormat,
+                                                                                                                               bool relaxedPrecision)
+       : BaseTestInstance              (context, texture, readFormat, true, true, false, false)
+       , m_imageDstFormat              (writeFormat)
+       , m_relaxedPrecision    (relaxedPrecision)
 {
        const DeviceInterface&          vk                              = m_context.getDeviceInterface();
        const VkDevice                          device                  = m_context.getDevice();
@@ -1973,8 +1986,10 @@ ImageExtendOperandTestInstance::ImageExtendOperandTestInstance (Context& context
        // Generate reference image
        m_isSigned = (getTextureChannelClass(textureFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
        m_inputImageData.setStorage(textureFormat, width, height, 1);
-       const tcu::PixelBufferAccess access = m_inputImageData.getAccess();
-       int valueStart = m_isSigned ? -width / 2 : 0;
+
+       const tcu::PixelBufferAccess    access          = m_inputImageData.getAccess();
+       const int                                               valueStart      = (m_isSigned ? (-width / 2) : 0);
+
        for (int x = 0; x < width; ++x)
        for (int y = 0; y < height; ++y)
        {
@@ -1989,7 +2004,6 @@ ImageExtendOperandTestInstance::ImageExtendOperandTestInstance (Context& context
                MemoryRequirement::Any));
 
        // Create destination image
-       m_imageDstFormat        = m_isSigned ? VK_FORMAT_R32G32B32A32_SINT : VK_FORMAT_R32G32B32A32_UINT;
        m_imageDst = de::MovePtr<Image>(new Image(
                vk, device, allocator,
                makeImageCreateInfo(m_texture, m_imageDstFormat, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u),
@@ -2103,6 +2117,19 @@ void ImageExtendOperandTestInstance::commandAfterCompute (const VkCommandBuffer
        commandCopyImageToBuffer(m_context, cmdBuffer, m_imageDst->get(), m_buffer->get(), m_imageDstSize, m_texture);
 }
 
+// Clears the high bits of every pixel in the pixel buffer, leaving only the lowest 16 bits of each component.
+void clearHighBits (const tcu::PixelBufferAccess& pixels, int width, int height)
+{
+       for (int y = 0; y < height; ++y)
+       for (int x = 0; x < width; ++x)
+       {
+               auto color = pixels.getPixelUint(x, y);
+               for (int c = 0; c < decltype(color)::SIZE; ++c)
+                       color[c] &= 0xFFFFull;
+               pixels.setPixel(color, x, y);
+       }
+}
+
 tcu::TestStatus ImageExtendOperandTestInstance::verifyResult (void)
 {
        const DeviceInterface&                  vk                      = m_context.getDeviceInterface();
@@ -2123,71 +2150,115 @@ tcu::TestStatus ImageExtendOperandTestInstance::verifyResult (void)
 
        const Allocation& alloc = m_buffer->getAllocation();
        invalidateAlloc(vk, device, alloc);
-       const tcu::ConstPixelBufferAccess result(mapVkFormat(m_imageDstFormat), imageSize, alloc.getHostPtr());
+       const tcu::PixelBufferAccess result(mapVkFormat(m_imageDstFormat), imageSize, alloc.getHostPtr());
 
-       if (intThresholdCompare (m_context.getTestContext().getLog(), "Comparison", "Comparison", refAccess, result, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT))
+       if (m_relaxedPrecision)
+       {
+               // Preserve the lowest 16 bits of the reference and result pixels only.
+               clearHighBits(refAccess, width, height);
+               clearHighBits(result, width, height);
+       }
+
+       if (tcu::intThresholdCompare (m_context.getTestContext().getLog(), "Comparison", "Comparison", refAccess, result, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT, true/*use64Bits*/))
                return tcu::TestStatus::pass("Passed");
        else
                return tcu::TestStatus::fail("Image comparison failed");
 }
 
+enum class ExtendTestType
+{
+       READ  = 0,
+       WRITE = 1,
+};
+
+enum class ExtendOperand
+{
+       SIGN_EXTEND = 0,
+       ZERO_EXTEND = 1
+};
+
 class ImageExtendOperandTest : public TestCase
 {
 public:
                                                        ImageExtendOperandTest  (tcu::TestContext&                                      testCtx,
                                                                                                         const std::string&                                     name,
                                                                                                         const Texture                                          texture,
-                                                                                                        const VkFormat                                         format,
+                                                                                                        const VkFormat                                         readFormat,
+                                                                                                        const VkFormat                                         writeFormat,
                                                                                                         const bool                                                     signedInt,
-                                                                                                        const bool                                                     relaxedPrecision);
+                                                                                                        const bool                                                     relaxedPrecision,
+                                                                                                        ExtendTestType                                         extendTestType);
 
        void                                    checkSupport                    (Context&                               context) const;
        void                                    initPrograms                    (SourceCollections&             programCollection) const;
        TestInstance*                   createInstance                  (Context&                               context) const;
 
 private:
-       const Texture                                   m_texture;
-       VkFormat                                                m_format;
-       bool                                                    m_operandForce; // Use an operand that doesn't match SampledType?
-       bool                                                    m_relaxedPrecision;
+       bool                                    isWriteTest                             () const { return (m_extendTestType == ExtendTestType::WRITE); }
+
+       const Texture                   m_texture;
+       VkFormat                                m_readFormat;
+       VkFormat                                m_writeFormat;
+       bool                                    m_operandForce;                 // Use an operand that doesn't match SampledType?
+       bool                                    m_relaxedPrecision;
+       ExtendTestType                  m_extendTestType;
 };
 
 ImageExtendOperandTest::ImageExtendOperandTest (tcu::TestContext&                              testCtx,
                                                                                                const std::string&                              name,
                                                                                                const Texture                                   texture,
-                                                                                               const VkFormat                                  format,
+                                                                                               const VkFormat                                  readFormat,
+                                                                                               const VkFormat                                  writeFormat,
                                                                                                const bool                                              operandForce,
-                                                                                               const bool                                              relaxedPrecision)
+                                                                                               const bool                                              relaxedPrecision,
+                                                                                               ExtendTestType                                  extendTestType)
        : TestCase                                              (testCtx, name, "")
        , m_texture                                             (texture)
-       , m_format                                              (format)
+       , m_readFormat                                  (readFormat)
+       , m_writeFormat                                 (writeFormat)
        , m_operandForce                                (operandForce)
        , m_relaxedPrecision                    (relaxedPrecision)
+       , m_extendTestType                              (extendTestType)
 {
 }
 
-void ImageExtendOperandTest::checkSupport (Context& context) const
+void checkFormatProperties (Context& context, VkFormat format)
 {
-       const vk::VkFormatProperties    formatProperties        (vk::getPhysicalDeviceFormatProperties(context.getInstanceInterface(),
-                                                                                                                                                                                          context.getPhysicalDevice(),
-                                                                                                                                                                                          m_format));
+       const VkFormatProperties3KHR formatProperties (context.getFormatProperties(format));
+
+       if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
+               TCU_THROW(NotSupportedError, "Format not supported for storage images");
+}
+
+void check64BitSupportIfNeeded (Context& context, VkFormat readFormat, VkFormat writeFormat)
+{
+       if (is64BitIntegerFormat(readFormat) || is64BitIntegerFormat(writeFormat))
+       {
+               const auto& features = context.getDeviceFeatures();
+               if (!features.shaderInt64)
+                       TCU_THROW(NotSupportedError, "64-bit integers not supported in shaders");
+       }
+}
 
+void ImageExtendOperandTest::checkSupport (Context& context) const
+{
        if (!context.requireDeviceFunctionality("VK_KHR_spirv_1_4"))
                TCU_THROW(NotSupportedError, "VK_KHR_spirv_1_4 not supported");
 
-       if ((m_texture.type() != IMAGE_TYPE_BUFFER) && !(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
-               TCU_THROW(NotSupportedError, "Format not supported for storage images");
+       check64BitSupportIfNeeded(context, m_readFormat, m_writeFormat);
 
-       if (m_texture.type() == IMAGE_TYPE_BUFFER && !(formatProperties.bufferFeatures & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT))
-               TCU_THROW(NotSupportedError, "Format not supported for storage texel buffers");
+       checkFormatProperties(context, m_readFormat);
+       checkFormatProperties(context, m_writeFormat);
 }
 
 void ImageExtendOperandTest::initPrograms (SourceCollections& programCollection) const
 {
        tcu::StringTemplate shaderTemplate(
                "OpCapability Shader\n"
+               "OpCapability StorageImageExtendedFormats\n"
 
                "${capability}"
+               "${extension}"
 
                "%std450 = OpExtInstImport \"GLSL.std.450\"\n"
                "OpMemoryModel Logical GLSL450\n"
@@ -2211,10 +2282,13 @@ void ImageExtendOperandTest::initPrograms (SourceCollections& programCollection)
                "%type_void                          = OpTypeVoid\n"
                "%type_i32                           = OpTypeInt 32 1\n"
                "%type_u32                           = OpTypeInt 32 0\n"
+               "%type_vec2_i32                      = OpTypeVector %type_i32 2\n"
+               "%type_vec2_u32                      = OpTypeVector %type_u32 2\n"
                "%type_vec3_i32                      = OpTypeVector %type_i32 3\n"
                "%type_vec3_u32                      = OpTypeVector %type_u32 3\n"
                "%type_vec4_i32                      = OpTypeVector %type_i32 4\n"
                "%type_vec4_u32                      = OpTypeVector %type_u32 4\n"
+               "${extra_types}"
 
                "%type_fun_void                      = OpTypeFunction %type_void\n"
 
@@ -2236,64 +2310,54 @@ void ImageExtendOperandTest::initPrograms (SourceCollections& programCollection)
 
                "${image_load}"
 
-               "%coord                              = OpLoad %type_vec3_u32 %id\n"
-               "%value                              = OpImageRead ${read_vect4_type} %src_image %coord ${extend_operand}\n"
-               "                                      OpImageWrite %dst_image %coord %value ${extend_operand}\n"
+               "%idvec                              = OpLoad %type_vec3_u32 %id\n"
+               "%id_xy                              = OpVectorShuffle %type_vec2_u32 %idvec %idvec 0 1\n"
+               "%coord                              = OpBitcast %type_vec2_i32 %id_xy\n"
+               "%value                              = OpImageRead ${sampled_type_vec4} %src_image %coord ${read_extend_operand}\n"
+               "                                      OpImageWrite %dst_image %coord %value ${write_extend_operand}\n"
                "                                      OpReturn\n"
                "                                      OpFunctionEnd\n");
 
-       tcu::TextureFormat      tcuFormat                       = mapVkFormat(m_format);
-       const ImageType         usedImageType           = getImageTypeForSingleLayer(m_texture.type());
-       const std::string       imageTypeStr            = getShaderImageType(tcuFormat, usedImageType);
-       const bool                      isSigned                        = (getTextureChannelClass(tcuFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
+       const auto      testedFormat    = mapVkFormat(isWriteTest() ? m_writeFormat : m_readFormat);
+       const bool      isSigned                = (getTextureChannelClass(testedFormat.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER);
 
-       struct FormatData
-       {
-               std::string             spirvImageFormat;
-               bool                    isExtendedFormat;
-       };
-       const std::map<vk::VkFormat, FormatData> formatDataMap =
-       {
-               // Mandatory support
-               { VK_FORMAT_R32G32B32A32_UINT,                  { "Rgba32ui",   false } },
-               { VK_FORMAT_R16G16B16A16_UINT,                  { "Rgba16ui",   false } },
-               { VK_FORMAT_R8G8B8A8_UINT,                              { "Rgba8ui",    false } },
-               { VK_FORMAT_R32_UINT,                                   { "R32ui",              false } },
-               { VK_FORMAT_R32G32B32A32_SINT,                  { "Rgba32i",    false } },
-               { VK_FORMAT_R16G16B16A16_SINT,                  { "Rgba16i",    false } },
-               { VK_FORMAT_R8G8B8A8_SINT,                              { "Rgba8i",             false } },
-               { VK_FORMAT_R32_SINT,                                   { "R32i",               false } },
-
-               // Requires StorageImageExtendedFormats capability
-               { VK_FORMAT_R32G32_UINT,                                { "Rg32ui",             true } },
-               { VK_FORMAT_R16G16_UINT,                                { "Rg16ui",             true } },
-               { VK_FORMAT_R16_UINT,                                   { "R16ui",              true } },
-               { VK_FORMAT_R8G8_UINT,                                  { "Rg8ui",              true } },
-               { VK_FORMAT_R8_UINT,                                    { "R8ui",               true } },
-               { VK_FORMAT_R32G32_SINT,                                { "Rg32i",              true } },
-               { VK_FORMAT_R16G16_SINT,                                { "Rg16i",              true } },
-               { VK_FORMAT_R16_SINT,                                   { "R16i",               true } },
-               { VK_FORMAT_R8G8_SINT,                                  { "Rg8i",               true } },
-               { VK_FORMAT_R8_SINT,                                    { "R8i",                true } },
-               { VK_FORMAT_A2B10G10R10_UINT_PACK32,    { "Rgb10a2ui",  true } }
-       };
+       const auto isRead64             = is64BitIntegerFormat(m_readFormat);
+       const auto isWrite64    = is64BitIntegerFormat(m_writeFormat);
+       DE_ASSERT(isRead64 == isWrite64);
+
+       const bool using64Bits                          = (isRead64 || isWrite64);
 
-       auto it = formatDataMap.find(m_format);
-       DE_ASSERT (it != formatDataMap.end());          // Missing int format data
-       auto spirvImageFormat = it->second.spirvImageFormat;
+       // Additional capabilities when needed.
+       std::string capability;
+       std::string extension;
+       std::string extraTypes;
 
-       // Request additional capability when needed
-       std::string capability = "";
-       if (it->second.isExtendedFormat)
-               capability += "OpCapability StorageImageExtendedFormats\n";
+       if (using64Bits)
+       {
+                       extension  += "OpExtension \"SPV_EXT_shader_image_int64\"\n";
+                       capability +=
+                               "OpCapability Int64\n"
+                               "OpCapability Int64ImageEXT\n"
+                               ;
+                       extraTypes +=
+                               "%type_i64                           = OpTypeInt 64 1\n"
+                               "%type_u64                           = OpTypeInt 64 0\n"
+                               "%type_vec3_i64                      = OpTypeVector %type_i64 3\n"
+                               "%type_vec3_u64                      = OpTypeVector %type_u64 3\n"
+                               "%type_vec4_i64                      = OpTypeVector %type_i64 4\n"
+                               "%type_vec4_u64                      = OpTypeVector %type_u64 4\n"
+                               ;
+       }
 
        std::string relaxed = "";
        if (m_relaxedPrecision)
                relaxed += "OpDecorate %src_image_ptr RelaxedPrecision\n";
 
-       // Use i32 SampledType only for signed images and only where we're not forcing
-       // the signedness usingthe SignExtend operand. Everything else uses u32.
-       std::string readTypePostfix = (isSigned && !m_operandForce) ? "i32" : "u32";
+       // Sampled type depends on the format sign and mismatch force flag.
+       const bool                      signedSampleType        = ((isSigned && !m_operandForce) || (!isSigned && m_operandForce));
+       const std::string       bits                            = (using64Bits ? "64" : "32");
+       const std::string       sampledTypePostfix      = (signedSampleType ? "i" : "u") + bits;
+       const std::string       extendOperandStr        = (isSigned ? "SignExtend" : "ZeroExtend");
 
        std::map<std::string, std::string> specializations =
        {
@@ -2302,11 +2366,14 @@ void ImageExtendOperandTest::initPrograms (SourceCollections& programCollection)
                { "image_var_id",                       "%src_image_ptr" },
                { "image_id",                           "%src_image" },
                { "capability",                         capability },
+               { "extension",                          extension },
+               { "extra_types",                        extraTypes },
                { "relaxed_precision",          relaxed },
-               { "image_format",                       spirvImageFormat },
-               { "sampled_type",                       (std::string("%type_") + readTypePostfix) },
-               { "read_vect4_type",            (std::string("%type_vec4_") + readTypePostfix) },
-               { "extend_operand",                     (isSigned ? "SignExtend" : "ZeroExtend") }
+               { "image_format",                       getSpirvFormat(m_readFormat) },
+               { "sampled_type",                       (std::string("%type_") + sampledTypePostfix) },
+               { "sampled_type_vec4",          (std::string("%type_vec4_") + sampledTypePostfix) },
+               { "read_extend_operand",        (!isWriteTest() ? extendOperandStr : "") },
+               { "write_extend_operand",       (isWriteTest()  ? extendOperandStr : "") },
        };
 
        // Addidtional parametrization is needed for a case when source and destination textures have same format
@@ -2325,7 +2392,7 @@ void ImageExtendOperandTest::initPrograms (SourceCollections& programCollection)
        std::string imageLoad;
 
        // If input image format is the same as output there is less spir-v definitions
-       if ((m_format == VK_FORMAT_R32G32B32A32_SINT) || (m_format == VK_FORMAT_R32G32B32A32_UINT))
+       if (m_readFormat == m_writeFormat)
        {
                imageTypes                      = imageTypeTemplate.specialize(specializations);
                imageUniformTypes       = imageUniformTypeTemplate.specialize(specializations);
@@ -2346,7 +2413,7 @@ void ImageExtendOperandTest::initPrograms (SourceCollections& programCollection)
                imageVariables          = imageVariablesTemplate.specialize(specializations);
                imageLoad                       = imageLoadTemplate.specialize(specializations);
 
-               specializations["image_format"]                         = isSigned ? "Rgba32i" : "Rgba32ui";
+               specializations["image_format"]                         = getSpirvFormat(m_writeFormat);
                specializations["image_type_id"]                        = "%type_dst_image";
                specializations["image_uni_ptr_type_id"]        = "%type_ptr_uniform_const_dst_image";
                specializations["image_var_id"]                         = "%dst_image_ptr";
@@ -2369,7 +2436,7 @@ void ImageExtendOperandTest::initPrograms (SourceCollections& programCollection)
 
 TestInstance* ImageExtendOperandTest::createInstance(Context& context) const
 {
-       return new ImageExtendOperandTestInstance(context, m_texture, m_format);
+       return new ImageExtendOperandTestInstance(context, m_texture, m_readFormat, m_writeFormat, m_relaxedPrecision);
 }
 
 static const Texture s_textures[] =
@@ -2396,7 +2463,6 @@ const Texture& getTestTexture (const ImageType imageType)
 
 static const VkFormat s_formats[] =
 {
-       // Mandatory support
        VK_FORMAT_R32G32B32A32_SFLOAT,
        VK_FORMAT_R16G16B16A16_SFLOAT,
        VK_FORMAT_R32_SFLOAT,
@@ -2413,9 +2479,11 @@ static const VkFormat s_formats[] =
 
        VK_FORMAT_R8G8B8A8_UNORM,
 
+       VK_FORMAT_B8G8R8A8_UNORM,
+       VK_FORMAT_B8G8R8A8_UINT,
+
        VK_FORMAT_R8G8B8A8_SNORM,
 
-       // Requires StorageImageExtendedFormats capability
        VK_FORMAT_B10G11R11_UFLOAT_PACK32,
 
        VK_FORMAT_R32G32_SFLOAT,
@@ -2482,17 +2550,21 @@ tcu::TestCaseGroup* createImageStoreTests (tcu::TestContext& testCtx)
 
                for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
                {
-                       groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx]));
+                       const bool hasSpirvFmt = hasSpirvFormat(s_formats[formatNdx]);
+
+                       if (hasSpirvFmt)
+                               groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx]));
                        groupWithoutFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], 0));
 
-                       if (isLayered)
+                       if (isLayered && hasSpirvFmt)
                                groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_single_layer", "",
                                                                                                                 texture, s_formats[formatNdx],
                                                                                                                 StoreTest::FLAG_SINGLE_LAYER_BIND | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
 
                        if (texture.type() == IMAGE_TYPE_BUFFER)
                        {
-                               groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], StoreTest::FLAG_MINALIGN | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
+                               if (hasSpirvFmt)
+                                       groupWithFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], StoreTest::FLAG_MINALIGN | StoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
                                groupWithoutFormatByImageViewType->addChild(new StoreTest(testCtx, getFormatShortString(s_formats[formatNdx]) + "_minalign", "", texture, s_formats[formatNdx], StoreTest::FLAG_MINALIGN));
                        }
                }
@@ -2522,6 +2594,11 @@ tcu::TestCaseGroup* createImageLoadStoreTests (tcu::TestContext& testCtx)
 
                for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
                {
+                       // These tests always require a SPIR-V format for the write image, even if the read
+                       // image is being used without a format.
+                       if (!hasSpirvFormat(s_formats[formatNdx]))
+                               continue;
+
                        groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx]));
                        groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], 0));
 
@@ -2586,6 +2663,11 @@ tcu::TestCaseGroup* createImageLoadStoreLodAMDTests (tcu::TestContext& testCtx)
 
                for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
                {
+                       // These tests always require a SPIR-V format for the write image, even if the read
+                       // image is being used without a format.
+                       if (!hasSpirvFormat(s_formats[formatNdx]))
+                               continue;
+
                        groupWithFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER, DE_TRUE));
                        groupWithoutFormatByImageViewType->addChild(new LoadStoreTest(testCtx, getFormatShortString(s_formats[formatNdx]), "", texture, s_formats[formatNdx], s_formats[formatNdx], 0, DE_TRUE));
 
@@ -2617,6 +2699,9 @@ tcu::TestCaseGroup* createImageFormatReinterpretTests (tcu::TestContext& testCtx
                for (int imageFormatNdx = 0; imageFormatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++imageFormatNdx)
                for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
                {
+                       if (!hasSpirvFormat(s_formats[formatNdx]))
+                               continue;
+
                        const std::string caseName = getFormatShortString(s_formats[imageFormatNdx]) + "_" + getFormatShortString(s_formats[formatNdx]);
                        if (imageFormatNdx != formatNdx && formatsAreCompatible(s_formats[imageFormatNdx], s_formats[formatNdx]))
                                groupByImageViewType->addChild(new LoadStoreTest(testCtx, caseName, "", texture, s_formats[formatNdx], s_formats[imageFormatNdx]));
@@ -2634,36 +2719,125 @@ de::MovePtr<TestCase> createImageQualifierRestrictCase (tcu::TestContext& testCt
        return de::MovePtr<TestCase>(new LoadStoreTest(testCtx, name, "", texture, format, format, LoadStoreTest::FLAG_RESTRICT_IMAGES | LoadStoreTest::FLAG_DECLARE_IMAGE_FORMAT_IN_SHADER));
 }
 
-static bool relaxedOK(VkFormat format)
+namespace
+{
+
+bool relaxedOK(VkFormat format)
 {
        tcu::IVec4 bitDepth = tcu::getTextureFormatBitDepth(mapVkFormat(format));
        int maxBitDepth = deMax32(deMax32(bitDepth[0], bitDepth[1]), deMax32(bitDepth[2], bitDepth[3]));
        return maxBitDepth <= 16;
 }
 
+// Get a format used for reading or writing in extension operand tests. These formats allow representing the shader sampled type to
+// verify results from read or write operations.
+VkFormat getShaderExtensionOperandFormat (bool isSigned, bool is64Bit)
+{
+       const VkFormat formats[] =
+       {
+               VK_FORMAT_R32G32B32A32_UINT,
+               VK_FORMAT_R32G32B32A32_SINT,
+               VK_FORMAT_R64_UINT,
+               VK_FORMAT_R64_SINT,
+       };
+       return formats[2u * (is64Bit ? 1u : 0u) + (isSigned ? 1u : 0u)];
+}
+
+// INT or UINT format?
+bool isIntegralFormat (VkFormat format)
+{
+       return (isIntFormat(format) || isUintFormat(format));
+}
+
+// Return the list of formats used for the extension operand tests (SignExten/ZeroExtend).
+std::vector<VkFormat> getExtensionOperandFormatList (void)
+{
+       std::vector<VkFormat> formatList;
+
+       for (auto format : s_formats)
+       {
+               if (isIntegralFormat(format))
+                       formatList.push_back(format);
+       }
+
+       formatList.push_back(VK_FORMAT_R64_SINT);
+       formatList.push_back(VK_FORMAT_R64_UINT);
+
+       return formatList;
+}
+
+} // anonymous
+
 tcu::TestCaseGroup* createImageExtendOperandsTests(tcu::TestContext& testCtx)
 {
-       de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "extend_operands_spirv1p4", "Cases with SignExtend and ZeroExtend"));
+       using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
 
-       const auto texture = Texture(IMAGE_TYPE_2D, tcu::IVec3(8, 8, 1), 1);
-       for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(s_formats); ++formatNdx)
+       GroupPtr testGroup(new tcu::TestCaseGroup(testCtx, "extend_operands_spirv1p4", "Cases with SignExtend and ZeroExtend"));
+
+       const struct
        {
-               auto format = s_formats[formatNdx];
-               if (!isIntFormat(format) && !isUintFormat(format))
-                       continue;
+               ExtendTestType  testType;
+               const char*             name;
+       } testTypes[] =
+       {
+               { ExtendTestType::READ,         "read"  },
+               { ExtendTestType::WRITE,        "write" },
+       };
+
+       const auto texture              = Texture(IMAGE_TYPE_2D, tcu::IVec3(8, 8, 1), 1);
+       const auto formatList   = getExtensionOperandFormatList();
+
+       for (const auto format : formatList)
+       {
+               const auto isInt                = isIntFormat(format);
+               const auto isUint               = isUintFormat(format);
+               const auto use64Bits    = is64BitIntegerFormat(format);
+
+               DE_ASSERT(isInt || isUint);
+
+               GroupPtr formatGroup (new tcu::TestCaseGroup(testCtx, getFormatShortString(format).c_str(), ""));
 
-               for (int prec = 0; prec < 2; prec++)
+               for (const auto& testType : testTypes)
                {
-                       bool relaxedPrecision = (prec != 0);
-                       if (relaxedPrecision && !relaxedOK(format))
-                               continue;
+                       GroupPtr testTypeGroup (new tcu::TestCaseGroup(testCtx, testType.name, ""));
+
+                       for (int match = 0; match < 2; ++match)
+                       {
+                               const bool      mismatched              = (match == 1);
+                               const char*     matchGroupName  = (mismatched ? "mismatched_sign" : "matched_sign");
+
+                               // SPIR-V does not allow this kind of sampled type override.
+                               if (mismatched && isUint)
+                                       continue;
+
+                               GroupPtr matchGroup (new tcu::TestCaseGroup(testCtx, matchGroupName, ""));
+
+                               for (int prec = 0; prec < 2; prec++)
+                               {
+                                       const bool relaxedPrecision = (prec != 0);
+
+                                       const char* precisionName       = (relaxedPrecision ? "relaxed_precision" : "normal_precision");
+                                       const auto  signedOther         = ((isInt && !mismatched) || (isUint && mismatched));
+                                       const auto      otherFormat             = getShaderExtensionOperandFormat(signedOther, use64Bits);
+                                       const auto  readFormat          = (testType.testType == ExtendTestType::READ ?  format : otherFormat);
+                                       const auto  writeFormat         = (testType.testType == ExtendTestType::WRITE ? format : otherFormat);
 
-                       const std::string name = getFormatShortString(format) + (relaxedPrecision ? "_relaxed" : "");
-                       testGroup->addChild(new ImageExtendOperandTest(testCtx, name + "_matching_extend", texture, format, false, relaxedPrecision));
-                       // For signed types test both using the sign bit in SPIR-V and the new operand
-                       if (isIntFormat(format))
-                               testGroup->addChild(new ImageExtendOperandTest(testCtx, name + "_force_sign_extend", texture, format, true, relaxedPrecision));
+                                       if (relaxedPrecision && !relaxedOK(readFormat))
+                                               continue;
+
+                                       if (!hasSpirvFormat(readFormat) || !hasSpirvFormat(writeFormat))
+                                               continue;
+
+                                       matchGroup->addChild(new ImageExtendOperandTest(testCtx, precisionName, texture, readFormat, writeFormat, mismatched, relaxedPrecision, testType.testType));
+                               }
+
+                               testTypeGroup->addChild(matchGroup.release());
+                       }
+
+                       formatGroup->addChild(testTypeGroup.release());
                }
+
+               testGroup->addChild(formatGroup.release());
        }
 
        return testGroup.release();