Add shader image access tests for the VK_KHR_protected_memory extension
authorJanos Pantos <jp.uszeged@partner.samsung.com>
Fri, 7 Jul 2017 17:33:49 +0000 (19:33 +0200)
committerPeter Gal <pgal.u-szeged@partner.samsung.com>
Thu, 7 Sep 2017 16:53:56 +0000 (18:53 +0200)
New tests:
dEQP-VK.protected_memory.image.access.*

Components: Vulkan
VK-GL-CTS issue: 118

Change-Id: I423396f3f814090e4506197723f0d0cdbbba0777

AndroidGen.mk
android/cts/master/vk-master.txt
external/vulkancts/modules/vulkan/protected_memory/CMakeLists.txt
external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemImageValidator.cpp
external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemImageValidator.hpp
external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemShaderImageAccessTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemShaderImageAccessTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemTests.cpp
external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemUtils.cpp
external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemUtils.hpp
external/vulkancts/mustpass/1.0.3/vk-default.txt

index 6341317..3f3cd6c 100644 (file)
@@ -173,6 +173,7 @@ LOCAL_SRC_FILES := \
        external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemCopyImageToBufferTests.cpp \
        external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemFillUpdateCopyBufferTests.cpp \
        external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemImageValidator.cpp \
+       external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemShaderImageAccessTests.cpp \
        external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemStorageBufferTests.cpp \
        external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemTests.cpp \
        external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemUtils.cpp \
index 07871b3..4fd456a 100755 (executable)
@@ -265478,6 +265478,55 @@ dEQP-VK.protected_memory.image.copy_buffer_to_image.secondary.random.copy_7
 dEQP-VK.protected_memory.image.copy_buffer_to_image.secondary.random.copy_8
 dEQP-VK.protected_memory.image.copy_buffer_to_image.secondary.random.copy_9
 dEQP-VK.protected_memory.image.copy_buffer_to_image.secondary.random.copy_10
+dEQP-VK.protected_memory.image.access.fragment.sampling.rgba8
+dEQP-VK.protected_memory.image.access.fragment.sampling.r32i
+dEQP-VK.protected_memory.image.access.fragment.sampling.r32ui
+dEQP-VK.protected_memory.image.access.fragment.texelfetch.rgba8
+dEQP-VK.protected_memory.image.access.fragment.texelfetch.r32i
+dEQP-VK.protected_memory.image.access.fragment.texelfetch.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imageload.rgba8
+dEQP-VK.protected_memory.image.access.fragment.imageload.r32i
+dEQP-VK.protected_memory.image.access.fragment.imageload.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imagestore.rgba8
+dEQP-VK.protected_memory.image.access.fragment.imagestore.r32i
+dEQP-VK.protected_memory.image.access.fragment.imagestore.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.add.r32i
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.add.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.min.r32i
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.min.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.max.r32i
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.max.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.and.r32i
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.and.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.or.r32i
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.or.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.xor.r32i
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.xor.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.exchange.r32i
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.exchange.r32ui
+dEQP-VK.protected_memory.image.access.compute.sampling.rgba8
+dEQP-VK.protected_memory.image.access.compute.sampling.r32i
+dEQP-VK.protected_memory.image.access.compute.sampling.r32ui
+dEQP-VK.protected_memory.image.access.compute.texelfetch.rgba8
+dEQP-VK.protected_memory.image.access.compute.texelfetch.r32i
+dEQP-VK.protected_memory.image.access.compute.texelfetch.r32ui
+dEQP-VK.protected_memory.image.access.compute.imageload.rgba8
+dEQP-VK.protected_memory.image.access.compute.imageload.r32i
+dEQP-VK.protected_memory.image.access.compute.imageload.r32ui
+dEQP-VK.protected_memory.image.access.compute.imageatomics.add.r32i
+dEQP-VK.protected_memory.image.access.compute.imageatomics.add.r32ui
+dEQP-VK.protected_memory.image.access.compute.imageatomics.min.r32i
+dEQP-VK.protected_memory.image.access.compute.imageatomics.min.r32ui
+dEQP-VK.protected_memory.image.access.compute.imageatomics.max.r32i
+dEQP-VK.protected_memory.image.access.compute.imageatomics.max.r32ui
+dEQP-VK.protected_memory.image.access.compute.imageatomics.and.r32i
+dEQP-VK.protected_memory.image.access.compute.imageatomics.and.r32ui
+dEQP-VK.protected_memory.image.access.compute.imageatomics.or.r32i
+dEQP-VK.protected_memory.image.access.compute.imageatomics.or.r32ui
+dEQP-VK.protected_memory.image.access.compute.imageatomics.xor.r32i
+dEQP-VK.protected_memory.image.access.compute.imageatomics.xor.r32ui
+dEQP-VK.protected_memory.image.access.compute.imageatomics.exchange.r32i
+dEQP-VK.protected_memory.image.access.compute.imageatomics.exchange.r32ui
 dEQP-VK.protected_memory.buffer.fill.float_buffer.primary.static.test_1
 dEQP-VK.protected_memory.buffer.fill.float_buffer.primary.static.test_2
 dEQP-VK.protected_memory.buffer.fill.float_buffer.primary.static.test_3
index 5fb5066..c312b9d 100644 (file)
@@ -28,6 +28,10 @@ set(DEQP_VK_PROTECTED_MEMORY_SRCS
        vktProtectedMemCopyBufferToImageTests.cpp
        vktProtectedMemStorageBufferTests.cpp
        vktProtectedMemStorageBufferTests.hpp
+       vktProtectedMemShaderImageAccessTests.cpp
+       vktProtectedMemShaderImageAccessTests.hpp
+       vktProtectedMemTests.cpp
+       vktProtectedMemTests.hpp
        )
 
 set(DEQP_VK_PROTECTED_MEMORY_LIBS
index a168f12..569b5ee 100644 (file)
 #include "vktProtectedMemImageValidator.hpp"
 
 #include "tcuTestLog.hpp"
+#include "tcuStringTemplate.hpp"
 
 #include "vkBuilderUtil.hpp"
 #include "vkPrograms.hpp"
 #include "vkTypeUtil.hpp"
+#include "vkImageUtil.hpp"
 #include "vktTestCase.hpp"
 #include "vktTestGroupUtil.hpp"
 
 #include "vktProtectedMemUtils.hpp"
 #include "vktProtectedMemContext.hpp"
+
 namespace vkt
 {
 namespace ProtectedMem
@@ -42,13 +45,13 @@ namespace ProtectedMem
 void ImageValidator::initPrograms (vk::SourceCollections& programCollection) const
 {
        // Layout:
-       //  set = 0, location = 0 -> uniform sampler2D u_protectedImage
+       //  set = 0, location = 0 -> uniform *sampler2D u_protectedImage
        //  set = 0, location = 1 -> buffer ProtectedHelper (2 * uint)
        //  set = 0, location = 2 -> uniform Data (2 * vec2 + 4 * vec4)
        const char* validatorShader = "#version 450\n"
                                          "layout(local_size_x = 1) in;\n"
                                          "\n"
-                                         "layout(set=0, binding=0) uniform sampler2D u_protectedImage;\n"
+                                         "layout(set=0, binding=0) uniform ${SAMPLER_TYPE} u_protectedImage;\n"
                                          "\n"
                                          "layout(set=0, binding=1) buffer ProtectedHelper\n"
                                          "{\n"
@@ -98,7 +101,12 @@ void ImageValidator::initPrograms (vk::SourceCollections& programCollection) con
                                          "}\n";
 
        programCollection.glslSources.add("ResetSSBO") << glu::ComputeSource(resetSSBOShader);
-       programCollection.glslSources.add("ImageValidator") << glu::ComputeSource(validatorShader);
+
+       std::map<std::string, std::string> validationParams;
+       validationParams["SAMPLER_TYPE"] = isIntFormat(m_imageFormat)   ? "isampler2D" :
+                                                                          isUintFormat(m_imageFormat)  ? "usampler2D" : "sampler2D";
+
+       programCollection.glslSources.add("ImageValidator") << glu::ComputeSource(tcu::StringTemplate(validatorShader).specialize(validationParams));
 }
 
 bool ImageValidator::validateImage (ProtectedContext& ctx, const ValidationData& refData,
index e37e652..47f5cf5 100644 (file)
@@ -36,14 +36,15 @@ namespace ProtectedMem
 class ProtectedContext;
 
 struct ValidationData {
-       const tcu::Vec4 coords[4];
-       const tcu::Vec4 values[4];
+       tcu::Vec4       coords[4];
+       tcu::Vec4       values[4];
 };
 
 class ImageValidator
 {
 public:
-                                                       ImageValidator  (void)
+                                                       ImageValidator  (vk::VkFormat imageFormat = vk::VK_FORMAT_R8G8B8A8_UNORM)
+                                                               : m_imageFormat (imageFormat)
                                                        {}
                                                        ~ImageValidator () {}
        void                                    initPrograms    (vk::SourceCollections& programCollection) const;
@@ -52,6 +53,9 @@ public:
                                                                                         const ValidationData&  refData,
                                                                                         const vk::VkImage              image,
                                                                                         const vk::VkFormat             imageFormat) const;
+
+private:
+       const vk::VkFormat              m_imageFormat;
 };
 
 } // ProtectedMem
diff --git a/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemShaderImageAccessTests.cpp b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemShaderImageAccessTests.cpp
new file mode 100644 (file)
index 0000000..ed1790a
--- /dev/null
@@ -0,0 +1,1513 @@
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * 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
+ * \brief Protected memory image access tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktProtectedMemShaderImageAccessTests.hpp"
+
+#include "vktProtectedMemContext.hpp"
+#include "vktProtectedMemUtils.hpp"
+#include "vktProtectedMemImageValidator.hpp"
+#include "vktTestCase.hpp"
+#include "vktTestGroupUtil.hpp"
+
+#include "vkPrograms.hpp"
+#include "vkTypeUtil.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkImageUtil.hpp"
+
+#include "tcuTestLog.hpp"
+#include "tcuVector.hpp"
+#include "tcuTextureUtil.hpp"
+#include "tcuStringTemplate.hpp"
+
+#include "gluTextureTestUtil.hpp"
+
+#include "deRandom.hpp"
+
+namespace vkt
+{
+namespace ProtectedMem
+{
+
+namespace
+{
+
+enum
+{
+       RENDER_WIDTH    = 128,
+       RENDER_HEIGHT   = 128,
+       IMAGE_WIDTH             = 128,
+       IMAGE_HEIGHT    = 128,
+};
+
+enum AccessType
+{
+       ACCESS_TYPE_SAMPLING = 0,
+       ACCESS_TYPE_TEXEL_FETCH,
+       ACCESS_TYPE_IMAGE_LOAD,
+       ACCESS_TYPE_IMAGE_STORE,
+       ACCESS_TYPE_IMAGE_ATOMICS,
+
+       ACCESS_TYPE_LAST
+};
+
+enum AtomicOperation
+{
+       ATOMIC_OPERATION_ADD = 0,
+       ATOMIC_OPERATION_MIN,
+       ATOMIC_OPERATION_MAX,
+       ATOMIC_OPERATION_AND,
+       ATOMIC_OPERATION_OR,
+       ATOMIC_OPERATION_XOR,
+       ATOMIC_OPERATION_EXCHANGE,
+
+       ATOMIC_OPERATION_LAST
+};
+
+struct Params
+{
+       glu::ShaderType         shaderType;
+       AccessType                      accessType;
+       vk::VkFormat            imageFormat;
+       AtomicOperation         atomicOperation;
+
+       Params (void)
+               : shaderType            (glu::SHADERTYPE_LAST)
+               , accessType            (ACCESS_TYPE_LAST)
+               , imageFormat           (vk::VK_FORMAT_UNDEFINED)
+               , atomicOperation       (ATOMIC_OPERATION_LAST)
+       {}
+
+       Params (const glu::ShaderType   shaderType_,
+                       const AccessType                accessType_,
+                       const vk::VkFormat              imageFormat_,
+                       const AtomicOperation   atomicOperation_        = ATOMIC_OPERATION_LAST)
+               : shaderType            (shaderType_)
+               , accessType            (accessType_)
+               , imageFormat           (imageFormat_)
+               , atomicOperation       (atomicOperation_)
+       {}
+};
+
+static deUint32 getSeedValue (const Params& params)
+{
+       return deInt32Hash(params.shaderType) ^ deInt32Hash(params.accessType) ^ deInt32Hash(params.imageFormat) ^ deInt32Hash(params.atomicOperation);
+}
+
+static std::string getAtomicOperationCaseName (const AtomicOperation op)
+{
+       switch (op)
+       {
+               case ATOMIC_OPERATION_ADD:                      return "add";
+               case ATOMIC_OPERATION_MIN:                      return "min";
+               case ATOMIC_OPERATION_MAX:                      return "max";
+               case ATOMIC_OPERATION_AND:                      return "and";
+               case ATOMIC_OPERATION_OR:                       return "or";
+               case ATOMIC_OPERATION_XOR:                      return "xor";
+               case ATOMIC_OPERATION_EXCHANGE:         return "exchange";
+               default:
+                       DE_FATAL("Impossible");
+                       return "";
+       }
+}
+
+static std::string getAtomicOperationShaderFuncName (const AtomicOperation op)
+{
+       switch (op)
+       {
+               case ATOMIC_OPERATION_ADD:                      return "imageAtomicAdd";
+               case ATOMIC_OPERATION_MIN:                      return "imageAtomicMin";
+               case ATOMIC_OPERATION_MAX:                      return "imageAtomicMax";
+               case ATOMIC_OPERATION_AND:                      return "imageAtomicAnd";
+               case ATOMIC_OPERATION_OR:                       return "imageAtomicOr";
+               case ATOMIC_OPERATION_XOR:                      return "imageAtomicXor";
+               case ATOMIC_OPERATION_EXCHANGE:         return "imageAtomicExchange";
+               default:
+                       DE_FATAL("Impossible");
+                       return "";
+       }
+}
+
+//! Computes the result of an atomic operation where "a" is the data operated on and "b" is the parameter to the atomic function.
+static deInt32 computeBinaryAtomicOperationResult (const AtomicOperation op, const deInt32 a, const deInt32 b)
+{
+       switch (op)
+       {
+               case ATOMIC_OPERATION_ADD:                      return a + b;
+               case ATOMIC_OPERATION_MIN:                      return de::min(a, b);
+               case ATOMIC_OPERATION_MAX:                      return de::max(a, b);
+               case ATOMIC_OPERATION_AND:                      return a & b;
+               case ATOMIC_OPERATION_OR:                       return a | b;
+               case ATOMIC_OPERATION_XOR:                      return a ^ b;
+               case ATOMIC_OPERATION_EXCHANGE:         return b;
+               default:
+                       DE_FATAL("Impossible");
+                       return -1;
+       }
+}
+
+static std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format)
+{
+       const char* orderPart;
+       const char* typePart;
+
+       switch (format.order)
+       {
+               case tcu::TextureFormat::R:             orderPart = "r";        break;
+               case tcu::TextureFormat::RG:    orderPart = "rg";       break;
+               case tcu::TextureFormat::RGB:   orderPart = "rgb";      break;
+               case tcu::TextureFormat::RGBA:  orderPart = "rgba";     break;
+
+               default:
+                       DE_FATAL("Impossible");
+                       orderPart = DE_NULL;
+       }
+
+       switch (format.type)
+       {
+               case tcu::TextureFormat::FLOAT:                         typePart = "32f";               break;
+               case tcu::TextureFormat::HALF_FLOAT:            typePart = "16f";               break;
+
+               case tcu::TextureFormat::UNSIGNED_INT32:        typePart = "32ui";              break;
+               case tcu::TextureFormat::UNSIGNED_INT16:        typePart = "16ui";              break;
+               case tcu::TextureFormat::UNSIGNED_INT8:         typePart = "8ui";               break;
+
+               case tcu::TextureFormat::SIGNED_INT32:          typePart = "32i";               break;
+               case tcu::TextureFormat::SIGNED_INT16:          typePart = "16i";               break;
+               case tcu::TextureFormat::SIGNED_INT8:           typePart = "8i";                break;
+
+               case tcu::TextureFormat::UNORM_INT16:           typePart = "16";                break;
+               case tcu::TextureFormat::UNORM_INT8:            typePart = "8";                 break;
+
+               case tcu::TextureFormat::SNORM_INT16:           typePart = "16_snorm";  break;
+               case tcu::TextureFormat::SNORM_INT8:            typePart = "8_snorm";   break;
+
+               default:
+                       DE_FATAL("Impossible");
+                       typePart = DE_NULL;
+       }
+
+       return std::string() + orderPart + typePart;
+}
+
+static std::string getShaderSamplerOrImageType (const tcu::TextureFormat& format, bool isSampler)
+{
+       const std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
+                                                                  tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER   ? "i" : "";
+
+       return formatPart + (isSampler ? "sampler2D" : "image2D");
+}
+
+class ImageAccessTestInstance : public ProtectedTestInstance
+{
+public:
+                                                               ImageAccessTestInstance (Context&                               ctx,
+                                                                                                                const ImageValidator&  validator,
+                                                                                                                const Params&                  params);
+       virtual tcu::TestStatus         iterate                                 (void);
+
+private:
+       de::MovePtr<tcu::Texture2D>     createTestTexture2D             (void);
+       void                                            clearImage                              (vk::VkImage                    image);
+       void                                            uploadImage                             (vk::VkImage                    image,
+                                                                                                                const tcu::Texture2D&  texture2D);
+       void                                            copyToProtectedImage    (vk::VkImage                    srcImage,
+                                                                                                                vk::VkImage                    dstImage);
+       void                                            calculateAtomicRef              (tcu::Texture2D&                texture2D);
+       tcu::TestStatus                         validateResult                  (vk::VkImage                    image,
+                                                                                                                const tcu::Texture2D&  texture2D,
+                                                                                                                const tcu::Sampler&    refSampler);
+
+       tcu::TestStatus                         executeFragmentTest             (void);
+       tcu::TestStatus                         executeComputeTest              (void);
+
+       const ImageValidator&           m_validator;
+       const Params&                           m_params;
+};
+
+class ImageAccessTestCase : public TestCase
+{
+public:
+                                                               ImageAccessTestCase             (tcu::TestContext&              testCtx,
+                                                                                                                const std::string&             name,
+                                                                                                                const std::string&             description,
+                                                                                                                const Params&                  params)
+                                                                       : TestCase              (testCtx, name, description)
+                                                                       , m_validator   (params.imageFormat)
+                                                                       , m_params              (params)
+                                                               {
+                                                               }
+
+       virtual                                         ~ImageAccessTestCase    (void) {}
+       virtual TestInstance*           createInstance                  (Context& ctx) const
+                                                               {
+                                                                       return new ImageAccessTestInstance(ctx, m_validator, m_params);
+                                                               }
+       virtual void                            initPrograms                    (vk::SourceCollections& programCollection) const;
+
+private:
+       ImageValidator                          m_validator;
+       Params                                          m_params;
+};
+
+void ImageAccessTestCase::initPrograms (vk::SourceCollections& programCollection) const
+{
+       const tcu::TextureFormat&       texFormat               = mapVkFormat(m_params.imageFormat);
+       const std::string                       imageFormat             = getShaderImageFormatQualifier(texFormat);
+       const std::string                       imageType               = getShaderSamplerOrImageType(texFormat, false);
+       const std::string                       samplerType             = getShaderSamplerOrImageType(texFormat, true);
+       const std::string                       colorVecType    = isIntFormat(m_params.imageFormat)             ? "ivec4" :
+                                                                                                 isUintFormat(m_params.imageFormat)    ? "uvec4" : "vec4";
+
+       m_validator.initPrograms(programCollection);
+
+       if (m_params.shaderType == glu::SHADERTYPE_FRAGMENT)
+       {
+               {
+                       // Vertex shader
+                       const char* vert = "#version 450\n"
+                                                          "layout(location = 0) in mediump vec2 a_position;\n"
+                                                          "layout(location = 1) in mediump vec2 a_texCoord;\n"
+                                                          "layout(location = 0) out mediump vec2 v_texCoord;\n"
+                                                          "\n"
+                                                          "void main() {\n"
+                                                          "    gl_Position = vec4(a_position, 0.0, 1.0);\n"
+                                                          "    v_texCoord = a_texCoord;\n"
+                                                          "}\n";
+
+                       programCollection.glslSources.add("vert") << glu::VertexSource(vert);
+               }
+
+               {
+                       // Fragment shader
+                       std::ostringstream frag;
+                       frag << "#version 450\n"
+                                       "layout(location = 0) in mediump vec2 v_texCoord;\n"
+                                       "layout(location = 0) out highp ${COLOR_VEC_TYPE} o_color;\n";
+
+                       switch (m_params.accessType)
+                       {
+                               case ACCESS_TYPE_SAMPLING:
+                               case ACCESS_TYPE_TEXEL_FETCH:
+                                       frag << "layout(set = 0, binding = 0) uniform highp ${SAMPLER_TYPE} u_sampler;\n";
+                                       break;
+                               case ACCESS_TYPE_IMAGE_LOAD:
+                                       frag << "layout(set = 0, binding = 0, ${IMAGE_FORMAT}) readonly uniform highp ${IMAGE_TYPE} u_image;\n";
+                                       break;
+                               case ACCESS_TYPE_IMAGE_STORE:
+                                       frag << "layout(set = 0, binding = 0, ${IMAGE_FORMAT}) readonly uniform highp ${IMAGE_TYPE} u_imageA;\n";
+                                       frag << "layout(set = 0, binding = 1, ${IMAGE_FORMAT}) writeonly uniform highp ${IMAGE_TYPE} u_imageB;\n";
+                                       break;
+                               case ACCESS_TYPE_IMAGE_ATOMICS:
+                                       frag << "layout(set = 0, binding = 0, ${IMAGE_FORMAT}) coherent uniform highp ${IMAGE_TYPE} u_image;\n";
+                                       break;
+                               default:
+                                       DE_FATAL("Impossible");
+                                       break;
+                       }
+
+                       frag << "\n"
+                                       "void main() {\n";
+
+                       switch (m_params.accessType)
+                       {
+                               case ACCESS_TYPE_SAMPLING:
+                                       frag << "    o_color = texture(u_sampler, v_texCoord);\n";
+                                       break;
+                               case ACCESS_TYPE_TEXEL_FETCH:
+                                       frag << "    const highp int lod = 0;\n";
+                                       frag << "    o_color = texelFetch(u_sampler, ivec2(v_texCoord), lod);\n";
+                                       break;
+                               case ACCESS_TYPE_IMAGE_LOAD:
+                                       frag << "    o_color = imageLoad(u_image, ivec2(v_texCoord));\n";
+                                       break;
+                               case ACCESS_TYPE_IMAGE_STORE:
+                                       frag << "    o_color = imageLoad(u_imageA, ivec2(v_texCoord));\n";
+                                       frag << "    imageStore(u_imageB, ivec2(v_texCoord), o_color);\n";
+                                       break;
+                               case ACCESS_TYPE_IMAGE_ATOMICS:
+                                       frag << "    int gx = int(v_texCoord.x);\n";
+                                       frag << "    int gy = int(v_texCoord.y);\n";
+                                       frag << "    "
+                                                << getAtomicOperationShaderFuncName(m_params.atomicOperation)
+                                                << "(u_image, ivec2(v_texCoord), "
+                                                << (isUintFormat(m_params.imageFormat) ? "uint" : "int")
+                                                << "(gx*gx + gy*gy));\n";
+                                       frag << "    o_color = imageLoad(u_image, ivec2(v_texCoord));\n";
+                                       break;
+                               default:
+                                       DE_FATAL("Impossible");
+                                       break;
+                       }
+
+                       frag << "}\n";
+
+                       std::map<std::string, std::string> fragParams;
+
+                       fragParams["IMAGE_FORMAT"]              = imageFormat;
+                       fragParams["IMAGE_TYPE"]                = imageType;
+                       fragParams["SAMPLER_TYPE"]              = samplerType;
+                       fragParams["COLOR_VEC_TYPE"]    = colorVecType;
+
+                       programCollection.glslSources.add("frag") << glu::FragmentSource(tcu::StringTemplate(frag.str()).specialize(fragParams));
+               }
+       }
+       else if (m_params.shaderType == glu::SHADERTYPE_COMPUTE)
+       {
+               // Compute shader
+               std::ostringstream comp;
+               comp << "#version 450\n"
+                               "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                               "layout(set = 0, binding = 0, ${IMAGE_FORMAT}) ${RES_MEM_QUALIFIER} uniform highp ${IMAGE_TYPE} u_resultImage;\n";
+
+               switch (m_params.accessType)
+               {
+                       case ACCESS_TYPE_SAMPLING:
+                       case ACCESS_TYPE_TEXEL_FETCH:
+                               comp << "layout(set = 0, binding = 1) uniform highp ${SAMPLER_TYPE} u_sampler;\n";
+                               break;
+                       case ACCESS_TYPE_IMAGE_LOAD:
+                       case ACCESS_TYPE_IMAGE_STORE:
+                               comp << "layout(set = 0, binding = 1, ${IMAGE_FORMAT}) readonly uniform highp ${IMAGE_TYPE} u_srcImage;\n";
+                               break;
+                       case ACCESS_TYPE_IMAGE_ATOMICS:
+                               break;
+                       default:
+                               DE_FATAL("Impossible");
+                               break;
+               }
+
+               comp << "\n"
+                               "void main() {\n"
+                               "    int gx = int(gl_GlobalInvocationID.x);\n"
+                               "    int gy = int(gl_GlobalInvocationID.y);\n";
+
+               switch (m_params.accessType)
+               {
+                       case ACCESS_TYPE_SAMPLING:
+                               comp << "    ${COLOR_VEC_TYPE} color = texture(u_sampler, vec2(float(gx)/" << de::toString((int)IMAGE_WIDTH) << ", float(gy)/" << de::toString((int)IMAGE_HEIGHT) << "));\n";
+                               comp << "    imageStore(u_resultImage, ivec2(gx, gy), color);\n";
+                               break;
+                       case ACCESS_TYPE_TEXEL_FETCH:
+                               comp << "    const highp int lod = 0;\n";
+                               comp << "    ${COLOR_VEC_TYPE} color = texelFetch(u_sampler, ivec2(gx, gy), lod);\n";
+                               comp << "    imageStore(u_resultImage, ivec2(gx, gy), color);\n";
+                               break;
+                       case ACCESS_TYPE_IMAGE_LOAD:
+                       case ACCESS_TYPE_IMAGE_STORE:
+                               comp << "    ${COLOR_VEC_TYPE} color = imageLoad(u_srcImage, ivec2(gx, gy));\n";
+                               comp << "    imageStore(u_resultImage, ivec2(gx, gy), color);\n";
+                               break;
+                       case ACCESS_TYPE_IMAGE_ATOMICS:
+                               comp << "    "
+                                        << getAtomicOperationShaderFuncName(m_params.atomicOperation)
+                                        << "(u_resultImage, ivec2(gx, gy), "
+                                        << (isUintFormat(m_params.imageFormat) ? "uint" : "int")
+                                        << "(gx*gx + gy*gy));\n";
+                               break;
+                       default:
+                               DE_FATAL("Impossible");
+                               break;
+               }
+
+               comp << "}\n";
+
+               std::map<std::string, std::string> compParams;
+
+               compParams["IMAGE_FORMAT"]              = imageFormat;
+               compParams["IMAGE_TYPE"]                = imageType;
+               compParams["SAMPLER_TYPE"]              = samplerType;
+               compParams["COLOR_VEC_TYPE"]    = colorVecType;
+               compParams["RES_MEM_QUALIFIER"] = m_params.accessType == ACCESS_TYPE_IMAGE_ATOMICS ? "coherent" : "writeonly";
+
+               programCollection.glslSources.add("comp") << glu::ComputeSource(tcu::StringTemplate(comp.str()).specialize(compParams));
+       }
+       else
+               DE_FATAL("Impossible");
+}
+
+ImageAccessTestInstance::ImageAccessTestInstance (Context&                                     ctx,
+                                                                                                 const ImageValidator&         validator,
+                                                                                                 const Params&                         params)
+       : ProtectedTestInstance (ctx)
+       , m_validator                   (validator)
+       , m_params                              (params)
+{
+}
+
+static void fillWithRandomColorTiles (const tcu::PixelBufferAccess& dst, const tcu::Vec4& minVal, const tcu::Vec4& maxVal, deUint32 seed)
+{
+       const int       numCols         = dst.getWidth()  >= 7 ? 7 : dst.getWidth();
+       const int       numRows         = dst.getHeight() >= 5 ? 5 : dst.getHeight();
+       de::Random      rnd                     (seed);
+
+       for (int slice = 0; slice < dst.getDepth(); slice++)
+       for (int row = 0; row < numRows; row++)
+       for (int col = 0; col < numCols; col++)
+       {
+               const int       yBegin  = (row + 0)*dst.getHeight() / numRows;
+               const int       yEnd    = (row + 1)*dst.getHeight() / numRows;
+               const int       xBegin  = (col + 0)*dst.getWidth() / numCols;
+               const int       xEnd    = (col + 1)*dst.getWidth() / numCols;
+               tcu::Vec4       color;
+               for (int i = 0; i < 4; i++)
+                       color[i] = rnd.getFloat(minVal[i], maxVal[i]);
+               tcu::clear(tcu::getSubregion(dst, xBegin, yBegin, slice, xEnd - xBegin, yEnd - yBegin, 1), color);
+       }
+}
+
+de::MovePtr<tcu::Texture2D> ImageAccessTestInstance::createTestTexture2D (void)
+{
+       const tcu::TextureFormat                texFmt          = mapVkFormat(m_params.imageFormat);
+       const tcu::TextureFormatInfo    fmtInfo         = tcu::getTextureFormatInfo(texFmt);
+       de::MovePtr<tcu::Texture2D>             texture2D       (new tcu::Texture2D(texFmt, IMAGE_WIDTH, IMAGE_HEIGHT));
+
+       // \note generate only the base level
+       texture2D->allocLevel(0);
+
+       const tcu::PixelBufferAccess&   level           = texture2D->getLevel(0);
+
+       if (m_params.accessType == ACCESS_TYPE_IMAGE_ATOMICS)
+       {
+               // use a smaller range than the format would allow
+               const float             cMin    = isIntFormat(m_params.imageFormat) ? -1000.0f : 0.0f;
+               const float             cMax    = +1000.0f;
+
+               fillWithRandomColorTiles(level, tcu::Vec4(cMin, 0, 0, 0), tcu::Vec4(cMax, 0, 0, 0), getSeedValue(m_params));
+       }
+       else
+               fillWithRandomColorTiles(level, fmtInfo.valueMin, fmtInfo.valueMax, getSeedValue(m_params));
+
+       return texture2D;
+}
+
+void ImageAccessTestInstance::uploadImage (vk::VkImage image, const tcu::Texture2D& texture2D)
+{
+       ProtectedContext&                                       ctx                                     (m_protectedContext);
+       const vk::DeviceInterface&                      vk                                      = ctx.getDeviceInterface();
+       const vk::VkDevice                                      device                          = ctx.getDevice();
+       const vk::VkQueue                                       queue                           = ctx.getQueue();
+       const deUint32                                          queueFamilyIndex        = ctx.getQueueFamilyIndex();
+
+       vk::Unique<vk::VkCommandPool>           cmdPool                         (makeCommandPool(vk, device, PROTECTION_DISABLED, queueFamilyIndex));
+       vk::Unique<vk::VkCommandBuffer>         cmdBuffer                       (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+
+       const deUint32                                          width                           = (deUint32)texture2D.getWidth();
+       const deUint32                                          height                          = (deUint32)texture2D.getHeight();
+       const deUint32                                          stagingBufferSize       = width * height * tcu::getPixelSize(texture2D.getFormat());
+
+       de::UniquePtr<vk::BufferWithMemory>     stagingBuffer           (makeBuffer(ctx,
+                                                                                                                                               PROTECTION_DISABLED,
+                                                                                                                                               queueFamilyIndex,
+                                                                                                                                               stagingBufferSize,
+                                                                                                                                               vk::VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
+                                                                                                                                               vk::MemoryRequirement::HostVisible));
+
+       {
+               const tcu::ConstPixelBufferAccess&      access          = texture2D.getLevel(0);
+               const tcu::PixelBufferAccess            destAccess      (access.getFormat(), access.getSize(), stagingBuffer->getAllocation().getHostPtr());
+
+               tcu::copy(destAccess, access);
+       }
+
+       const vk::VkImageSubresourceRange       subresourceRange        =
+       {
+               vk::VK_IMAGE_ASPECT_COLOR_BIT,  // VkImageAspectFlags   aspectMask
+               0u,                                                             // uint32_t                             baseMipLevel
+               1u,                                                             // uint32_t                             levelCount
+               0u,                                                             // uint32_t                             baseArrayLayer
+               1u,                                                             // uint32_t                             layerCount
+       };
+
+       const vk::VkImageMemoryBarrier          preCopyBarrier          =
+       {
+               vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,             // VkStructureType                      sType;
+               DE_NULL,                                                                                // const void*                          pNext;
+               0u,                                                                                             // VkAccessFlags                        srcAccessMask;
+               vk::VK_ACCESS_TRANSFER_WRITE_BIT,                               // VkAccessFlags                        dstAccessMask;
+               vk::VK_IMAGE_LAYOUT_UNDEFINED,                                  // VkImageLayout                        oldLayout;
+               vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,               // VkImageLayout                        newLayout;
+               queueFamilyIndex,                                                               // deUint32                                     srcQueueFamilyIndex;
+               queueFamilyIndex,                                                               // deUint32                                     dstQueueFamilyIndex;
+               image,                                                                                  // VkImage                                      image;
+               subresourceRange                                                                // VkImageSubresourceRange      subresourceRange;
+       };
+
+       const vk::VkImageMemoryBarrier          postCopyBarrier         =
+       {
+               vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,             // VkStructureType                      sType;
+               DE_NULL,                                                                                // const void*                          pNext;
+               vk::VK_ACCESS_TRANSFER_WRITE_BIT,                               // VkAccessFlags                        srcAccessMask;
+               vk::VK_ACCESS_TRANSFER_WRITE_BIT,                               // VkAccessFlags                        dstAccessMask;
+               vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,               // VkImageLayout                        oldLayout;
+               vk::VK_IMAGE_LAYOUT_GENERAL,                                    // VkImageLayout                        newLayout;
+               queueFamilyIndex,                                                               // deUint32                                     srcQueueFamilyIndex;
+               queueFamilyIndex,                                                               // deUint32                                     dstQueueFamilyIndex;
+               image,                                                                                  // VkImage                                      image;
+               subresourceRange                                                                // VkImageSubresourceRange      subresourceRange;
+       };
+
+       const vk::VkImageSubresourceLayers      subresourceLayers       =
+       {
+               vk::VK_IMAGE_ASPECT_COLOR_BIT,  // VkImageAspectFlags   aspectMask;
+               0u,                                                             // deUint32                             mipLevel;
+               0u,                                                             // deUint32                             baseArrayLayer;
+               1u                                                              // deUint32                             layerCount;
+       };
+
+       const vk::VkBufferImageCopy                     copyRegion                      =
+       {
+               0u,                                                             // VkDeviceSize                                 bufferOffset;
+               width,                                                  // deUint32                                             bufferRowLength;
+               height,                                                 // deUint32                                             bufferImageHeight;
+               subresourceLayers,                              // VkImageSubresourceLayers             imageSubresource;
+               { 0u, 0u, 0u },                                 // VkOffset3D                                   imageOffset;
+               { width, height, 1u }                   // VkExtent3D                                   imageExtent;
+       };
+
+       beginCommandBuffer(vk, *cmdBuffer);
+       vk.cmdPipelineBarrier(*cmdBuffer,
+                                                 (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_HOST_BIT,
+                                                 (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
+                                                 (vk::VkDependencyFlags)0u,
+                                                 0u, (const vk::VkMemoryBarrier*)DE_NULL,
+                                                 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL,
+                                                 1u, &preCopyBarrier);
+       vk.cmdCopyBufferToImage(*cmdBuffer, **stagingBuffer, image, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1u, &copyRegion);
+       vk.cmdPipelineBarrier(*cmdBuffer,
+                                                 (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
+                                                 (vk::VkPipelineStageFlags)vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+                                                 (vk::VkDependencyFlags)0u,
+                                                 0u, (const vk::VkMemoryBarrier*)DE_NULL,
+                                                 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL,
+                                                 1u, &postCopyBarrier);
+       VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+
+       {
+               const vk::Unique<vk::VkFence>   fence           (createFence(vk, device));
+               VK_CHECK(queueSubmit(ctx, PROTECTION_DISABLED, queue, *cmdBuffer, *fence, ~0ull));
+       }
+}
+
+void ImageAccessTestInstance::copyToProtectedImage (vk::VkImage srcImage, vk::VkImage dstImage)
+{
+       ProtectedContext&                                       ctx                                     (m_protectedContext);
+       const vk::DeviceInterface&                      vk                                      = ctx.getDeviceInterface();
+       const vk::VkDevice                                      device                          = ctx.getDevice();
+       const vk::VkQueue                                       queue                           = ctx.getQueue();
+       const deUint32                                          queueFamilyIndex        = ctx.getQueueFamilyIndex();
+
+       vk::Unique<vk::VkCommandPool>           cmdPool                         (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
+       vk::Unique<vk::VkCommandBuffer>         cmdBuffer                       (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+
+       const vk::VkImageSubresourceRange       subresourceRange        =
+       {
+               vk::VK_IMAGE_ASPECT_COLOR_BIT,  // VkImageAspectFlags   aspectMask
+               0u,                                                             // uint32_t                             baseMipLevel
+               1u,                                                             // uint32_t                             levelCount
+               0u,                                                             // uint32_t                             baseArrayLayer
+               1u,                                                             // uint32_t                             layerCount
+       };
+
+       const vk::VkImageMemoryBarrier          preImageBarriers[]      =
+       {
+               // source image
+               {
+                       vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,             // VkStructureType                      sType;
+                       DE_NULL,                                                                                // const void*                          pNext;
+                       vk::VK_ACCESS_TRANSFER_WRITE_BIT,                               // VkAccessFlags                        srcAccessMask;
+                       vk::VK_ACCESS_TRANSFER_READ_BIT,                                // VkAccessFlags                        dstAccessMask;
+                       vk::VK_IMAGE_LAYOUT_GENERAL,                                    // VkImageLayout                        oldLayout;
+                       vk::VK_IMAGE_LAYOUT_GENERAL,                                    // VkImageLayout                        newLayout;
+                       queueFamilyIndex,                                                               // deUint32                                     srcQueueFamilyIndex;
+                       queueFamilyIndex,                                                               // deUint32                                     dstQueueFamilyIndex;
+                       srcImage,                                                                               // VkImage                                      image;
+                       subresourceRange                                                                // VkImageSubresourceRange      subresourceRange;
+               },
+               // destination image
+               {
+                       vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,             // VkStructureType                      sType;
+                       DE_NULL,                                                                                // const void*                          pNext;
+                       0,                                                                                              // VkAccessFlags                        srcAccessMask;
+                       vk::VK_ACCESS_TRANSFER_WRITE_BIT,                               // VkAccessFlags                        dstAccessMask;
+                       vk::VK_IMAGE_LAYOUT_UNDEFINED,                                  // VkImageLayout                        oldLayout;
+                       vk::VK_IMAGE_LAYOUT_GENERAL,                                    // VkImageLayout                        newLayout;
+                       queueFamilyIndex,                                                               // deUint32                                     srcQueueFamilyIndex;
+                       queueFamilyIndex,                                                               // deUint32                                     dstQueueFamilyIndex;
+                       dstImage,                                                                               // VkImage                                      image;
+                       subresourceRange                                                                // VkImageSubresourceRange      subresourceRange;
+               }
+       };
+
+       const vk::VkImageMemoryBarrier          postImgBarrier          =
+       {
+               vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,             // VkStructureType                      sType;
+               DE_NULL,                                                                                // const void*                          pNext;
+               vk::VK_ACCESS_TRANSFER_WRITE_BIT,                               // VkAccessFlags                        srcAccessMask;
+               vk::VK_ACCESS_TRANSFER_WRITE_BIT,                               // VkAccessFlags                        dstAccessMask;
+               vk::VK_IMAGE_LAYOUT_GENERAL,                                    // VkImageLayout                        oldLayout;
+               vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,   // VkImageLayout                        newLayout;
+               queueFamilyIndex,                                                               // deUint32                                     srcQueueFamilyIndex;
+               queueFamilyIndex,                                                               // deUint32                                     dstQueueFamilyIndex;
+               dstImage,                                                                               // VkImage                                      image;
+               subresourceRange                                                                // VkImageSubresourceRange      subresourceRange;
+       };
+
+       const vk::VkImageSubresourceLayers      subresourceLayers       =
+       {
+               vk::VK_IMAGE_ASPECT_COLOR_BIT,  // VkImageAspectFlags   aspectMask;
+               0u,                                                             // deUint32                             mipLevel;
+               0u,                                                             // deUint32                             baseArrayLayer;
+               1u                                                              // deUint32                             layerCount;
+       };
+
+       const vk::VkImageCopy                           copyImageRegion         =
+       {
+               subresourceLayers,                                                                              // VkImageSubresourceCopy       srcSubresource;
+               { 0, 0, 0 },                                                                                    // VkOffset3D                           srcOffset;
+               subresourceLayers,                                                                              // VkImageSubresourceCopy       destSubresource;
+               { 0, 0, 0 },                                                                                    // VkOffset3D                           destOffset;
+               { (deUint32)IMAGE_WIDTH, (deUint32)IMAGE_HEIGHT, 1u },  // VkExtent3D                           extent;
+       };
+
+       beginCommandBuffer(vk, *cmdBuffer);
+       vk.cmdPipelineBarrier(*cmdBuffer,
+                                                 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
+                                                 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
+                                                 (vk::VkDependencyFlags)0,
+                                                 0, (const vk::VkMemoryBarrier*)DE_NULL,
+                                                 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
+                                                 DE_LENGTH_OF_ARRAY(preImageBarriers), preImageBarriers);
+       vk.cmdCopyImage(*cmdBuffer, srcImage, vk::VK_IMAGE_LAYOUT_GENERAL, dstImage, vk::VK_IMAGE_LAYOUT_GENERAL, 1u, &copyImageRegion);
+       vk.cmdPipelineBarrier(*cmdBuffer,
+                                                 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
+                                                 vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+                                                 (vk::VkDependencyFlags)0,
+                                                 0, (const vk::VkMemoryBarrier*)DE_NULL,
+                                                 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
+                                                 1, &postImgBarrier);
+       VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+
+       {
+               const vk::Unique<vk::VkFence>   fence           (createFence(vk, device));
+               VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
+       }
+}
+
+void ImageAccessTestInstance::clearImage (vk::VkImage image)
+{
+       ProtectedContext&                                       ctx                                     (m_protectedContext);
+       const vk::DeviceInterface&                      vk                                      = ctx.getDeviceInterface();
+       const vk::VkDevice                                      device                          = ctx.getDevice();
+       const vk::VkQueue                                       queue                           = ctx.getQueue();
+       const deUint32                                          queueFamilyIndex        = ctx.getQueueFamilyIndex();
+
+       vk::Unique<vk::VkCommandPool>           cmdPool                         (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
+       vk::Unique<vk::VkCommandBuffer>         cmdBuffer                       (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+
+       const vk::VkClearColorValue                     clearColor                      = { { 0.0f, 0.0f, 0.0f, 0.0f } };
+
+       const vk::VkImageSubresourceRange       subresourceRange        =
+       {
+               vk::VK_IMAGE_ASPECT_COLOR_BIT,  // VkImageAspectFlags   aspectMask
+               0u,                                                             // uint32_t                             baseMipLevel
+               1u,                                                             // uint32_t                             levelCount
+               0u,                                                             // uint32_t                             baseArrayLayer
+               1u,                                                             // uint32_t                             layerCount
+       };
+
+       const vk::VkImageMemoryBarrier          preImageBarrier         =
+       {
+               vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,             // VkStructureType                      sType;
+               DE_NULL,                                                                                // const void*                          pNext;
+               0u,                                                                                             // VkAccessFlags                        srcAccessMask;
+               vk::VK_ACCESS_TRANSFER_WRITE_BIT,                               // VkAccessFlags                        dstAccessMask;
+               vk::VK_IMAGE_LAYOUT_UNDEFINED,                                  // VkImageLayout                        oldLayout;
+               vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,               // VkImageLayout                        newLayout;
+               queueFamilyIndex,                                                               // deUint32                                     srcQueueFamilyIndex;
+               queueFamilyIndex,                                                               // deUint32                                     dstQueueFamilyIndex;
+               image,                                                                                  // VkImage                                      image;
+               subresourceRange                                                                // VkImageSubresourceRange      subresourceRange;
+       };
+
+       const vk::VkImageMemoryBarrier          postImageBarrier        =
+       {
+               vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,             // VkStructureType                      sType;
+               DE_NULL,                                                                                // const void*                          pNext;
+               vk::VK_ACCESS_TRANSFER_WRITE_BIT,                               // VkAccessFlags                        srcAccessMask;
+               vk::VK_ACCESS_TRANSFER_WRITE_BIT,                               // VkAccessFlags                        dstAccessMask;
+               vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,               // VkImageLayout                        oldLayout;
+               vk::VK_IMAGE_LAYOUT_GENERAL,                                    // VkImageLayout                        newLayout;
+               queueFamilyIndex,                                                               // deUint32                                     srcQueueFamilyIndex;
+               queueFamilyIndex,                                                               // deUint32                                     dstQueueFamilyIndex;
+               image,                                                                                  // VkImage                                      image;
+               subresourceRange                                                                // VkImageSubresourceRange      subresourceRange;
+       };
+
+       beginCommandBuffer(vk, *cmdBuffer);
+       vk.cmdPipelineBarrier(*cmdBuffer,
+                                                 vk::VK_PIPELINE_STAGE_HOST_BIT,
+                                                 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
+                                                 (vk::VkDependencyFlags)0,
+                                                 0, (const vk::VkMemoryBarrier*)DE_NULL,
+                                                 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
+                                                 1, &preImageBarrier);
+       vk.cmdClearColorImage(*cmdBuffer, image, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1, &subresourceRange);
+       vk.cmdPipelineBarrier(*cmdBuffer,
+                                                 vk::VK_PIPELINE_STAGE_TRANSFER_BIT,
+                                                 vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+                                                 (vk::VkDependencyFlags)0,
+                                                 0, (const vk::VkMemoryBarrier*)DE_NULL,
+                                                 0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
+                                                 1, &postImageBarrier);
+       VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+
+       {
+               const vk::Unique<vk::VkFence>   fence           (createFence(vk, device));
+               VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
+       }
+}
+
+tcu::TestStatus ImageAccessTestInstance::iterate (void)
+{
+       switch (m_params.shaderType)
+       {
+               case glu::SHADERTYPE_FRAGMENT:  return executeFragmentTest();
+               case glu::SHADERTYPE_COMPUTE:   return executeComputeTest();
+               default:
+                       DE_FATAL("Impossible");
+                       return tcu::TestStatus::fail("");
+       }
+}
+
+tcu::TestStatus ImageAccessTestInstance::executeComputeTest (void)
+{
+       ProtectedContext&                                       ctx                                     (m_protectedContext);
+       const vk::DeviceInterface&                      vk                                      = ctx.getDeviceInterface();
+       const vk::VkDevice                                      device                          = ctx.getDevice();
+       const vk::VkQueue                                       queue                           = ctx.getQueue();
+       const deUint32                                          queueFamilyIndex        = ctx.getQueueFamilyIndex();
+
+       vk::Unique<vk::VkCommandPool>           cmdPool                         (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
+
+       de::MovePtr<tcu::Texture2D>                     texture2D                       = createTestTexture2D();
+       const tcu::Sampler                                      refSampler                      = tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
+                                                                                                                                                  tcu::Sampler::NEAREST, tcu::Sampler::NEAREST);
+
+       vk::Unique<vk::VkShaderModule>          computeShader           (vk::createShaderModule(vk, device, ctx.getBinaryCollection().get("comp"), 0));
+
+       de::MovePtr<vk::ImageWithMemory>        imageSrc;
+       de::MovePtr<vk::ImageWithMemory>        imageDst;
+       vk::Move<vk::VkSampler>                         sampler;
+       vk::Move<vk::VkImageView>                       imageViewSrc;
+       vk::Move<vk::VkImageView>                       imageViewDst;
+
+       vk::Move<vk::VkDescriptorSetLayout>     descriptorSetLayout;
+       vk::Move<vk::VkDescriptorPool>          descriptorPool;
+       vk::Move<vk::VkDescriptorSet>           descriptorSet;
+
+       // Create src and dst images
+       {
+               vk::VkImageUsageFlags imageUsageFlags = vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT     |
+                                                                                               vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT     |
+                                                                                               vk::VK_IMAGE_USAGE_SAMPLED_BIT          |
+                                                                                               vk::VK_IMAGE_USAGE_STORAGE_BIT;
+
+               imageSrc = createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
+                                                                IMAGE_WIDTH, IMAGE_HEIGHT,
+                                                                m_params.imageFormat,
+                                                                imageUsageFlags);
+
+               if (m_params.accessType != ACCESS_TYPE_IMAGE_ATOMICS)
+               {
+                       imageDst = createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
+                                                                        IMAGE_WIDTH, IMAGE_HEIGHT,
+                                                                        m_params.imageFormat,
+                                                                        imageUsageFlags);
+               }
+       }
+
+       // Upload source image
+       {
+               de::MovePtr<vk::ImageWithMemory>        unprotectedImage        = createImage2D(ctx, PROTECTION_DISABLED, queueFamilyIndex,
+                                                                                                                                                               IMAGE_WIDTH, IMAGE_HEIGHT,
+                                                                                                                                                               m_params.imageFormat,
+                                                                                                                                                               vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
+
+               // Upload data to an unprotected image
+               uploadImage(**unprotectedImage, *texture2D);
+
+               // Copy unprotected image to protected image
+               copyToProtectedImage(**unprotectedImage, **imageSrc);
+       }
+
+       // Clear dst image
+       if (m_params.accessType != ACCESS_TYPE_IMAGE_ATOMICS)
+               clearImage(**imageDst);
+
+       // Create descriptors
+       {
+               vk::DescriptorSetLayoutBuilder  layoutBuilder;
+               vk::DescriptorPoolBuilder               poolBuilder;
+
+               switch (m_params.accessType)
+               {
+                       case ACCESS_TYPE_SAMPLING:
+                       case ACCESS_TYPE_TEXEL_FETCH:
+                               layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+                               layoutBuilder.addSingleSamplerBinding(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_SHADER_STAGE_COMPUTE_BIT, DE_NULL);
+                               poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u);
+                               poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u);
+                               break;
+                       case ACCESS_TYPE_IMAGE_LOAD:
+                       case ACCESS_TYPE_IMAGE_STORE:
+                               layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+                               layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+                               poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2u);
+                               break;
+                       case ACCESS_TYPE_IMAGE_ATOMICS:
+                               layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
+                               poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u);
+                               break;
+                       default:
+                               DE_FATAL("Impossible");
+                               break;
+               }
+
+               descriptorSetLayout             = layoutBuilder.build(vk, device);
+               descriptorPool                  = poolBuilder.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+               descriptorSet                   = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
+       }
+
+       // Create pipeline layout
+       vk::Unique<vk::VkPipelineLayout>        pipelineLayout          (makePipelineLayout(vk, device, *descriptorSetLayout));
+
+       // Create sampler and image views
+       {
+               if (m_params.accessType == ACCESS_TYPE_SAMPLING || m_params.accessType == ACCESS_TYPE_TEXEL_FETCH)
+               {
+                       const tcu::TextureFormat                texFormat               = mapVkFormat(m_params.imageFormat);
+                       const vk::VkSamplerCreateInfo   samplerParams   = vk::mapSampler(refSampler, texFormat);
+
+                       sampler = createSampler(vk, device, &samplerParams);
+               }
+
+               imageViewSrc = createImageView(ctx, **imageSrc, m_params.imageFormat);
+
+               if (m_params.accessType != ACCESS_TYPE_IMAGE_ATOMICS)
+                       imageViewDst = createImageView(ctx, **imageDst, m_params.imageFormat);
+       }
+
+       // Update descriptor set information
+       {
+               vk::DescriptorSetUpdateBuilder          updateBuilder;
+
+               switch (m_params.accessType)
+               {
+                       case ACCESS_TYPE_SAMPLING:
+                       case ACCESS_TYPE_TEXEL_FETCH:
+                       {
+                               vk::VkDescriptorImageInfo       descStorageImgDst       = makeDescriptorImageInfo((vk::VkSampler)0, *imageViewDst, vk::VK_IMAGE_LAYOUT_GENERAL);
+                               vk::VkDescriptorImageInfo       descSampledImgSrc       = makeDescriptorImageInfo(*sampler, *imageViewSrc, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+
+                               updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImgDst);
+                               updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descSampledImgSrc);
+                               break;
+                       }
+                       case ACCESS_TYPE_IMAGE_LOAD:
+                       case ACCESS_TYPE_IMAGE_STORE:
+                       {
+                               vk::VkDescriptorImageInfo       descStorageImgDst       = makeDescriptorImageInfo((vk::VkSampler)0, *imageViewDst, vk::VK_IMAGE_LAYOUT_GENERAL);
+                               vk::VkDescriptorImageInfo       descStorageImgSrc       = makeDescriptorImageInfo((vk::VkSampler)0, *imageViewSrc, vk::VK_IMAGE_LAYOUT_GENERAL);
+
+                               updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImgDst);
+                               updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImgSrc);
+                               break;
+                       }
+                       case ACCESS_TYPE_IMAGE_ATOMICS:
+                       {
+                               vk::VkDescriptorImageInfo       descStorageImg          = makeDescriptorImageInfo((vk::VkSampler)0, *imageViewSrc, vk::VK_IMAGE_LAYOUT_GENERAL);
+
+                               updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImg);
+                               break;
+                       }
+                       default:
+                               DE_FATAL("Impossible");
+                               break;
+               }
+
+               updateBuilder.update(vk, device);
+       }
+
+       // Create validation compute commands & submit
+       {
+               const vk::Unique<vk::VkFence>           fence           (vk::createFence(vk, device));
+               vk::Unique<vk::VkPipeline>                      pipeline        (makeComputePipeline(vk, device, *pipelineLayout, *computeShader, DE_NULL));
+               vk::Unique<vk::VkCommandBuffer>         cmdBuffer       (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+
+               beginCommandBuffer(vk, *cmdBuffer);
+
+               vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
+               vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
+               vk.cmdDispatch(*cmdBuffer, (deUint32)IMAGE_WIDTH, (deUint32)IMAGE_HEIGHT, 1u);
+               VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+
+               VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
+       }
+
+       // Calculate reference image
+       if (m_params.accessType == ACCESS_TYPE_IMAGE_ATOMICS)
+               calculateAtomicRef(*texture2D);
+
+       // Validate result
+       {
+               const vk::VkImage       resultImage             = m_params.accessType == ACCESS_TYPE_IMAGE_ATOMICS ? **imageSrc : **imageDst;
+
+               return validateResult(resultImage, *texture2D, refSampler);
+       }
+}
+
+tcu::TestStatus ImageAccessTestInstance::executeFragmentTest (void)
+{
+       ProtectedContext&                                       ctx                                     (m_protectedContext);
+       const vk::DeviceInterface&                      vk                                      = ctx.getDeviceInterface();
+       const vk::VkDevice                                      device                          = ctx.getDevice();
+       const vk::VkQueue                                       queue                           = ctx.getQueue();
+       const deUint32                                          queueFamilyIndex        = ctx.getQueueFamilyIndex();
+
+       // Create output image
+       de::MovePtr<vk::ImageWithMemory>        colorImage                      (createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
+                                                                                                                                                  RENDER_WIDTH, RENDER_HEIGHT,
+                                                                                                                                                  m_params.imageFormat,
+                                                                                                                                                  vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|vk::VK_IMAGE_USAGE_SAMPLED_BIT));
+       vk::Unique<vk::VkImageView>                     colorImageView          (createImageView(ctx, **colorImage, m_params.imageFormat));
+
+       vk::Unique<vk::VkRenderPass>            renderPass                      (createRenderPass(ctx, m_params.imageFormat));
+       vk::Unique<vk::VkFramebuffer>           framebuffer                     (createFramebuffer(ctx, RENDER_WIDTH, RENDER_HEIGHT, *renderPass, *colorImageView));
+
+       vk::Unique<vk::VkCommandPool>           cmdPool                         (makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
+       vk::Unique<vk::VkCommandBuffer>         cmdBuffer                       (vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+
+       de::MovePtr<tcu::Texture2D>                     texture2D                       = createTestTexture2D();
+       const tcu::Sampler                                      refSampler                      = tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
+                                                                                                                                                  tcu::Sampler::NEAREST, tcu::Sampler::NEAREST);
+
+       vk::Move<vk::VkShaderModule>            vertexShader            = createShaderModule(vk, device, ctx.getBinaryCollection().get("vert"), 0);
+       vk::Move<vk::VkShaderModule>            fragmentShader          = createShaderModule(vk, device, ctx.getBinaryCollection().get("frag"), 0);
+
+       de::MovePtr<vk::ImageWithMemory>        imageSrc;
+       de::MovePtr<vk::ImageWithMemory>        imageDst;
+       vk::Move<vk::VkSampler>                         sampler;
+       vk::Move<vk::VkImageView>                       imageViewSrc;
+       vk::Move<vk::VkImageView>                       imageViewDst;
+
+       vk::Move<vk::VkPipeline>                        graphicsPipeline;
+       vk::Move<vk::VkDescriptorSetLayout>     descriptorSetLayout;
+       vk::Move<vk::VkDescriptorPool>          descriptorPool;
+       vk::Move<vk::VkDescriptorSet>           descriptorSet;
+
+       // Create src and dst images
+       {
+               vk::VkImageUsageFlags imageUsageFlags = vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT     |
+                                                                                               vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT     |
+                                                                                               vk::VK_IMAGE_USAGE_SAMPLED_BIT;
+
+               switch (m_params.accessType)
+               {
+                       case ACCESS_TYPE_IMAGE_LOAD:
+                       case ACCESS_TYPE_IMAGE_STORE:
+                       case ACCESS_TYPE_IMAGE_ATOMICS:
+                               imageUsageFlags |= vk::VK_IMAGE_USAGE_STORAGE_BIT;
+                               break;
+                       default:
+                               break;
+               }
+
+               imageSrc = createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
+                                                                IMAGE_WIDTH, IMAGE_HEIGHT,
+                                                                m_params.imageFormat,
+                                                                imageUsageFlags);
+
+               if (m_params.accessType == ACCESS_TYPE_IMAGE_STORE)
+               {
+                       imageDst = createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
+                                                                        IMAGE_WIDTH, IMAGE_HEIGHT,
+                                                                        m_params.imageFormat,
+                                                                        imageUsageFlags);
+               }
+       }
+
+       // Upload source image
+       {
+               de::MovePtr<vk::ImageWithMemory>        unprotectedImage        = createImage2D(ctx, PROTECTION_DISABLED, queueFamilyIndex,
+                                                                                                                                                               IMAGE_WIDTH, IMAGE_HEIGHT,
+                                                                                                                                                               m_params.imageFormat,
+                                                                                                                                                               vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);
+
+               // Upload data to an unprotected image
+               uploadImage(**unprotectedImage, *texture2D);
+
+               // Copy unprotected image to protected image
+               copyToProtectedImage(**unprotectedImage, **imageSrc);
+       }
+
+       // Clear dst image
+       if (m_params.accessType == ACCESS_TYPE_IMAGE_STORE)
+               clearImage(**imageDst);
+
+       // Create descriptors
+       {
+               vk::DescriptorSetLayoutBuilder  layoutBuilder;
+               vk::DescriptorPoolBuilder               poolBuilder;
+
+               switch (m_params.accessType)
+               {
+                       case ACCESS_TYPE_SAMPLING:
+                       case ACCESS_TYPE_TEXEL_FETCH:
+                               layoutBuilder.addSingleSamplerBinding(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_SHADER_STAGE_FRAGMENT_BIT, DE_NULL);
+                               poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u);
+                               break;
+                       case ACCESS_TYPE_IMAGE_LOAD:
+                               layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
+                               poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u);
+                               break;
+                       case ACCESS_TYPE_IMAGE_STORE:
+                               layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
+                               layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
+                               poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2u);
+                               break;
+                       case ACCESS_TYPE_IMAGE_ATOMICS:
+                               layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
+                               poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u);
+                               break;
+                       default:
+                               DE_FATAL("Impossible");
+                               break;
+               }
+
+               descriptorSetLayout             = layoutBuilder.build(vk, device);
+               descriptorPool                  = poolBuilder.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+               descriptorSet                   = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
+       }
+
+       // Create pipeline layout
+       vk::Unique<vk::VkPipelineLayout>        pipelineLayout          (makePipelineLayout(vk, device, *descriptorSetLayout));
+
+       // Create sampler and image views
+       {
+               if (m_params.accessType == ACCESS_TYPE_SAMPLING || m_params.accessType == ACCESS_TYPE_TEXEL_FETCH)
+               {
+                       const tcu::TextureFormat                texFormat               = mapVkFormat(m_params.imageFormat);
+                       const vk::VkSamplerCreateInfo   samplerParams   = vk::mapSampler(refSampler, texFormat);
+
+                       sampler = createSampler(vk, device, &samplerParams);
+               }
+
+               imageViewSrc = createImageView(ctx, **imageSrc, m_params.imageFormat);
+
+               if (m_params.accessType == ACCESS_TYPE_IMAGE_STORE)
+                       imageViewDst = createImageView(ctx, **imageDst, m_params.imageFormat);
+       }
+
+       // Update descriptor set information
+       {
+               vk::DescriptorSetUpdateBuilder          updateBuilder;
+
+               switch (m_params.accessType)
+               {
+                       case ACCESS_TYPE_SAMPLING:
+                       case ACCESS_TYPE_TEXEL_FETCH:
+                       {
+                               vk::VkDescriptorImageInfo       descSampledImg          = makeDescriptorImageInfo(*sampler, *imageViewSrc, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
+
+                               updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descSampledImg);
+                               break;
+                       }
+                       case ACCESS_TYPE_IMAGE_LOAD:
+                       {
+                               vk::VkDescriptorImageInfo       descStorageImg          = makeDescriptorImageInfo((vk::VkSampler)0, *imageViewSrc, vk::VK_IMAGE_LAYOUT_GENERAL);
+
+                               updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImg);
+                               break;
+                       }
+                       case ACCESS_TYPE_IMAGE_STORE:
+                       {
+                               vk::VkDescriptorImageInfo       descStorageImgSrc       = makeDescriptorImageInfo((vk::VkSampler)0, *imageViewSrc, vk::VK_IMAGE_LAYOUT_GENERAL);
+                               vk::VkDescriptorImageInfo       descStorageImgDst       = makeDescriptorImageInfo((vk::VkSampler)0, *imageViewDst, vk::VK_IMAGE_LAYOUT_GENERAL);
+
+                               updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImgSrc);
+                               updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImgDst);
+                               break;
+                       }
+                       case ACCESS_TYPE_IMAGE_ATOMICS:
+                       {
+                               vk::VkDescriptorImageInfo       descStorageImg          = makeDescriptorImageInfo((vk::VkSampler)0, *imageViewSrc, vk::VK_IMAGE_LAYOUT_GENERAL);
+
+                               updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImg);
+                               break;
+                       }
+                       default:
+                               DE_FATAL("Impossible");
+                               break;
+               }
+
+               updateBuilder.update(vk, device);
+       }
+
+       // Create vertex buffer and vertex input descriptors
+       VertexBindings                                          vertexBindings;
+       VertexAttribs                                           vertexAttribs;
+       de::MovePtr<vk::BufferWithMemory>       vertexBuffer;
+       {
+               const float                     positions[]             =
+               {
+                       -1.0f,  -1.0f,
+                       -1.0f,  +1.0f,
+                       +1.0f,  -1.0f,
+                       +1.0f,  +1.0f,
+               };
+
+               std::vector<float>      texCoord;
+
+               {
+                       const tcu::Vec2         minCoords               (0.0f, 0.0f);
+                       const tcu::Vec2         maxCoords               = m_params.accessType == ACCESS_TYPE_SAMPLING ?
+                                                                                                 tcu::Vec2(1.0f, 1.0f) :
+                                                                                                 tcu::Vec2((float)IMAGE_WIDTH - 0.1f, (float)IMAGE_HEIGHT - 0.1f);
+
+                       glu::TextureTestUtil::computeQuadTexCoord2D(texCoord, minCoords, maxCoords);
+               }
+
+               const deUint32          vertexPositionStrideSize        = (deUint32)sizeof(tcu::Vec2);
+               const deUint32          vertexTextureStrideSize         = (deUint32)sizeof(tcu::Vec2);
+               const deUint32          positionDataSize                        = 4 * vertexPositionStrideSize;
+               const deUint32          textureCoordDataSize            = 4 * vertexTextureStrideSize;
+               const deUint32          vertexBufferSize                        = positionDataSize + textureCoordDataSize;
+
+               {
+                       const vk::VkVertexInputBindingDescription       vertexInputBindingDescriptions[2]       =
+                       {
+                               {
+                                       0u,                                                                     // deUint32                                     binding;
+                                       vertexPositionStrideSize,                       // deUint32                                     strideInBytes;
+                                       vk::VK_VERTEX_INPUT_RATE_VERTEX         // VkVertexInputStepRate        inputRate;
+                               },
+                               {
+                                       1u,                                                                     // deUint32                                     binding;
+                                       vertexTextureStrideSize,                        // deUint32                                     strideInBytes;
+                                       vk::VK_VERTEX_INPUT_RATE_VERTEX         // VkVertexInputStepRate        inputRate;
+                               }
+                       };
+                       vertexBindings.push_back(vertexInputBindingDescriptions[0]);
+                       vertexBindings.push_back(vertexInputBindingDescriptions[1]);
+
+                       const vk::VkVertexInputAttributeDescription     vertexInputAttributeDescriptions[2]     =
+                       {
+                               {
+                                       0u,                                                                     // deUint32     location;
+                                       0u,                                                                     // deUint32     binding;
+                                       vk::VK_FORMAT_R32G32_SFLOAT,            // VkFormat     format;
+                                       0u                                                                      // deUint32     offsetInBytes;
+                               },
+                               {
+                                       1u,                                                                     // deUint32     location;
+                                       1u,                                                                     // deUint32     binding;
+                                       vk::VK_FORMAT_R32G32_SFLOAT,            // VkFormat     format;
+                                       positionDataSize                                        // deUint32     offsetInBytes;
+                               }
+                       };
+                       vertexAttribs.push_back(vertexInputAttributeDescriptions[0]);
+                       vertexAttribs.push_back(vertexInputAttributeDescriptions[1]);
+               }
+
+               vertexBuffer = makeBuffer(ctx,
+                                                                 PROTECTION_DISABLED,
+                                                                 queueFamilyIndex,
+                                                                 vertexBufferSize,
+                                                                 vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
+                                                                 vk::MemoryRequirement::HostVisible);
+
+               deMemcpy(vertexBuffer->getAllocation().getHostPtr(), positions, positionDataSize);
+               deMemcpy(reinterpret_cast<deUint8*>(vertexBuffer->getAllocation().getHostPtr()) +  positionDataSize, texCoord.data(), textureCoordDataSize);
+               vk::flushMappedMemoryRange(vk, device, vertexBuffer->getAllocation().getMemory(), vertexBuffer->getAllocation().getOffset(), vertexBufferSize);
+       }
+
+       // Create pipeline
+       graphicsPipeline = makeGraphicsPipeline(vk,
+                                                                                       device,
+                                                                                       *pipelineLayout,
+                                                                                       *renderPass,
+                                                                                       *vertexShader,
+                                                                                       *fragmentShader,
+                                                                                       vertexBindings,
+                                                                                       vertexAttribs,
+                                                                                       tcu::UVec2(RENDER_WIDTH, RENDER_HEIGHT),
+                                                                                       vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
+
+       // Begin cmd buffer
+       beginCommandBuffer(vk, *cmdBuffer);
+
+       // Start image barrier
+       {
+               const vk::VkImageMemoryBarrier  startImgBarrier         =
+               {
+                       vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                     // sType
+                       DE_NULL,                                                                                        // pNext
+                       0,                                                                                                      // srcAccessMask
+                       vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                       // dstAccessMask
+                       vk::VK_IMAGE_LAYOUT_UNDEFINED,                                          // oldLayout
+                       vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,           // newLayout
+                       queueFamilyIndex,                                                                       // srcQueueFamilyIndex
+                       queueFamilyIndex,                                                                       // dstQueueFamilyIndex
+                       **colorImage,                                                                           // image
+                       {
+                               vk::VK_IMAGE_ASPECT_COLOR_BIT,                                  // aspectMask
+                               0u,                                                                                             // baseMipLevel
+                               1u,                                                                                             // mipLevels
+                               0u,                                                                                             // baseArraySlice
+                               1u,                                                                                             // subresourceRange
+                       }
+               };
+
+               vk.cmdPipelineBarrier(*cmdBuffer,
+                                                         vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+                                                         vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+                                                         (vk::VkDependencyFlags)0,
+                                                         0, (const vk::VkMemoryBarrier*)DE_NULL,
+                                                         0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
+                                                         1, &startImgBarrier);
+       }
+
+       const vk::VkClearValue                          clearValue                      = vk::makeClearValueColorF32(0.0f, 0.0f, 0.0f, 0.0f);
+       const vk::VkRenderPassBeginInfo         passBeginInfo           =
+       {
+               vk::VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,           // sType
+               DE_NULL,                                                                                        // pNext
+               *renderPass,                                                                            // renderPass
+               *framebuffer,                                                                           // framebuffer
+               { { 0, 0 }, { RENDER_WIDTH, RENDER_HEIGHT } },          // renderArea
+               1u,                                                                                                     // clearValueCount
+               &clearValue,                                                                            // pClearValues
+       };
+
+       vk.cmdBeginRenderPass(*cmdBuffer, &passBeginInfo, vk::VK_SUBPASS_CONTENTS_INLINE);
+
+       vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
+       vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
+
+       {
+               const vk::VkDeviceSize vertexBufferOffset = 0;
+
+               vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer->get(), &vertexBufferOffset);
+               vk.cmdBindVertexBuffers(*cmdBuffer, 1u, 1u, &vertexBuffer->get(), &vertexBufferOffset);
+       }
+
+       vk.cmdDraw(*cmdBuffer, /*vertexCount*/ 4u, 1u, 0u, 1u);
+
+       vk.cmdEndRenderPass(*cmdBuffer);
+
+       {
+               const vk::VkImageMemoryBarrier  endImgBarrier           =
+               {
+                       vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                     // sType
+                       DE_NULL,                                                                                        // pNext
+                       vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                       // srcAccessMask
+                       vk::VK_ACCESS_SHADER_READ_BIT,                                          // dstAccessMask
+                       vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,           // oldLayout
+                       vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,           // newLayout
+                       queueFamilyIndex,                                                                       // srcQueueFamilyIndex
+                       queueFamilyIndex,                                                                       // dstQueueFamilyIndex
+                       **colorImage,                                                                           // image
+                       {
+                               vk::VK_IMAGE_ASPECT_COLOR_BIT,                                  // aspectMask
+                               0u,                                                                                             // baseMipLevel
+                               1u,                                                                                             // mipLevels
+                               0u,                                                                                             // baseArraySlice
+                               1u,                                                                                             // subresourceRange
+                       }
+               };
+               vk.cmdPipelineBarrier(*cmdBuffer,
+                                                         vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+                                                         vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
+                                                         (vk::VkDependencyFlags)0,
+                                                         0, (const vk::VkMemoryBarrier*)DE_NULL,
+                                                         0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
+                                                         1, &endImgBarrier);
+       }
+
+       VK_CHECK(vk.endCommandBuffer(*cmdBuffer));
+
+       // Submit command buffer
+       {
+               const vk::Unique<vk::VkFence>   fence           (vk::createFence(vk, device));
+               VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
+       }
+
+       // Calculate reference image
+       if (m_params.accessType == ACCESS_TYPE_IMAGE_ATOMICS)
+               calculateAtomicRef(*texture2D);
+
+       // Validate result
+       {
+               const vk::VkImage       resultImage             = m_params.accessType == ACCESS_TYPE_IMAGE_ATOMICS      ?       **imageSrc      :
+                                                                                         m_params.accessType == ACCESS_TYPE_IMAGE_STORE        ?       **imageDst      : **colorImage;
+
+               return validateResult(resultImage, *texture2D, refSampler);
+       }
+}
+
+void ImageAccessTestInstance::calculateAtomicRef (tcu::Texture2D& texture2D)
+{
+       DE_ASSERT(m_params.accessType == ACCESS_TYPE_IMAGE_ATOMICS);
+
+       const tcu::PixelBufferAccess&   reference       = texture2D.getLevel(0);
+
+       for (int x = 0; x < reference.getWidth(); ++x)
+       for (int y = 0; y < reference.getHeight(); ++y)
+       {
+               const deInt32   oldX            = reference.getPixelInt(x, y).x();
+               const deInt32   atomicArg       = x*x + y*y;
+               const deInt32   newX            = computeBinaryAtomicOperationResult(m_params.atomicOperation, oldX, atomicArg);
+
+               reference.setPixel(tcu::IVec4(newX, 0, 0, 0), x, y);
+       }
+}
+
+tcu::TestStatus ImageAccessTestInstance::validateResult (vk::VkImage image, const tcu::Texture2D& texture2D, const tcu::Sampler& refSampler)
+{
+       de::Random                      rnd                     (getSeedValue(m_params));
+       ValidationData          refData;
+
+       for (int ndx = 0; ndx < 4; ++ndx)
+       {
+               const float             lod             = 0.0f;
+               const float             cx              = rnd.getFloat(0.0f, 1.0f);
+               const float             cy              = rnd.getFloat(0.0f, 1.0f);
+
+               refData.coords[ndx] = tcu::Vec4(cx, cy, 0.0f, 0.0f);
+               refData.values[ndx] = texture2D.sample(refSampler, cx, cy, lod);
+       }
+
+       if (!m_validator.validateImage(m_protectedContext, refData, image, m_params.imageFormat))
+               return tcu::TestStatus::fail("Something went really wrong");
+       else
+               return tcu::TestStatus::pass("Everything went OK");
+}
+
+} // anonymous
+
+tcu::TestCaseGroup*    createShaderImageAccessTests (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> accessGroup (new tcu::TestCaseGroup(testCtx, "access", "Shader Image Access Tests"));
+
+       static const struct
+       {
+               glu::ShaderType type;
+               const char*             name;
+               const char*             desc;
+       } shaderTypes[] =
+       {
+               { glu::SHADERTYPE_FRAGMENT,             "fragment",                     "Image access from fragment shader"             },
+               { glu::SHADERTYPE_COMPUTE,              "compute",                      "Image access from compute shader"              },
+       };
+
+       static const struct
+       {
+               AccessType              type;
+               const char*             name;
+               const char*             desc;
+       } accessTypes[] =
+       {
+               { ACCESS_TYPE_SAMPLING,                 "sampling",                     "Sampling test"                 },
+               { ACCESS_TYPE_TEXEL_FETCH,              "texelfetch",           "Texel fetch test"              },
+               { ACCESS_TYPE_IMAGE_LOAD,               "imageload",            "Image load test"               },
+               { ACCESS_TYPE_IMAGE_STORE,              "imagestore",           "Image store test"              },
+               { ACCESS_TYPE_IMAGE_ATOMICS,    "imageatomics",         "Image atomics test"    },
+       };
+
+       static const struct
+       {
+               vk::VkFormat    format;
+               const char*             name;
+       } formats[] =
+       {
+               { vk::VK_FORMAT_R8G8B8A8_UNORM, "rgba8" },
+               { vk::VK_FORMAT_R32_SINT,               "r32i"  },
+               { vk::VK_FORMAT_R32_UINT,               "r32ui" },
+       };
+
+       for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(shaderTypes); ++shaderTypeNdx)
+       {
+               const glu::ShaderType                           shaderType              = shaderTypes[shaderTypeNdx].type;
+               de::MovePtr<tcu::TestCaseGroup>         shaderGroup             (new tcu::TestCaseGroup(testCtx, shaderTypes[shaderTypeNdx].name, shaderTypes[shaderTypeNdx].desc));
+
+               for (int accessNdx = 0; accessNdx < DE_LENGTH_OF_ARRAY(accessTypes); ++accessNdx)
+               {
+                       const AccessType                                        accessType                      = accessTypes[accessNdx].type;
+
+                       if (shaderType == glu::SHADERTYPE_COMPUTE && accessType == ACCESS_TYPE_IMAGE_STORE) // \note already tested in other tests
+                               continue;
+
+                       de::MovePtr<tcu::TestCaseGroup>         accessTypeGroup         (new tcu::TestCaseGroup(testCtx, accessTypes[accessNdx].name, accessTypes[accessNdx].desc));
+
+                       if (accessType == ACCESS_TYPE_IMAGE_ATOMICS)
+                       {
+                               for (deUint32 atomicOpI = 0; atomicOpI < ATOMIC_OPERATION_LAST; ++atomicOpI)
+                               {
+                                       const AtomicOperation                           atomicOp                = (AtomicOperation)atomicOpI;
+                                       de::MovePtr<tcu::TestCaseGroup>         operationGroup  (new tcu::TestCaseGroup(testCtx, getAtomicOperationCaseName(atomicOp).c_str(), ""));
+
+                                       for (deUint32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
+                                       {
+                                               const vk::VkFormat              format          = formats[formatNdx].format;
+
+                                               if (format != vk::VK_FORMAT_R32_UINT && format != vk::VK_FORMAT_R32_SINT)
+                                                       continue;
+
+                                               operationGroup->addChild(new ImageAccessTestCase(testCtx, formats[formatNdx].name, "", Params(shaderType, accessType, format, atomicOp)));
+                                       }
+
+                                       accessTypeGroup->addChild(operationGroup.release());
+                               }
+                       }
+                       else
+                       {
+                               for (deUint32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
+                               {
+                                       const vk::VkFormat              format          = formats[formatNdx].format;
+
+                                       accessTypeGroup->addChild(new ImageAccessTestCase(testCtx, formats[formatNdx].name, "", Params(shaderType, accessType, format)));
+                               }
+                       }
+
+                       shaderGroup->addChild(accessTypeGroup.release());
+               }
+
+               accessGroup->addChild(shaderGroup.release());
+       }
+
+       return accessGroup.release();
+}
+
+} // ProtectedMem
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemShaderImageAccessTests.hpp b/external/vulkancts/modules/vulkan/protected_memory/vktProtectedMemShaderImageAccessTests.hpp
new file mode 100644 (file)
index 0000000..e008a1b
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef _VKTPROTECTEDMEMSHADERIMAGEACCESSTESTS_HPP
+#define _VKTPROTECTEDMEMSHADERIMAGEACCESSTESTS_HPP
+
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2017 The Khronos Group Inc.
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *
+ * 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
+ * \brief Protected memory image access tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace ProtectedMem
+{
+
+tcu::TestCaseGroup*            createShaderImageAccessTests    (tcu::TestContext& testCtx);
+
+} // ProtectedMem
+} // vkt
+
+#endif // _VKTPROTECTEDMEMSHADERIMAGEACCESSTESTS_HPP
index 2e91477..f46c57f 100644 (file)
@@ -36,6 +36,7 @@
 #include "vktProtectedMemCopyImageToBufferTests.hpp"
 #include "vktProtectedMemCopyBufferToImageTests.hpp"
 #include "vktProtectedMemStorageBufferTests.hpp"
+#include "vktProtectedMemShaderImageAccessTests.hpp"
 
 namespace vkt
 {
@@ -61,6 +62,7 @@ tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
                imageTestGroup->addChild(createBlitImageTests(testCtx));
                imageTestGroup->addChild(createClearColorImageTests(testCtx));
                imageTestGroup->addChild(createCopyBufferToImageTests(testCtx));
+               imageTestGroup->addChild(createShaderImageAccessTests(testCtx));
                protectedTests->addChild(imageTestGroup.release());
        }
 
@@ -82,6 +84,7 @@ tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx)
                ssboTestGroup->addChild(createAtomicStorageBufferTests(testCtx));
                protectedTests->addChild(ssboTestGroup.release());
        }
+
        return protectedTests.release();
 
 }
index e1014a0..8866368 100644 (file)
@@ -584,6 +584,7 @@ vk::Move<vk::VkPipeline> makeGraphicsPipeline (const vk::DeviceInterface&           vk,
                        DE_NULL                                                                                                         // const VkSpecializationInfo*                  pSpecializationInfo;
                }
        };
+
        const vk::VkPipelineVertexInputStateCreateInfo          vertexInputStateParams          =
        {
                vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,  // VkStructureType                                                      sType;
@@ -594,6 +595,7 @@ vk::Move<vk::VkPipeline> makeGraphicsPipeline (const vk::DeviceInterface&           vk,
                (deUint32)vertexAttribs.size(),                                                                 // deUint32                                                                     attributeCount;
                vertexAttribs.data()                                                                                    // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
        };
+
        const vk::VkPipelineInputAssemblyStateCreateInfo        inputAssemblyStateParams        =
        {
                vk::VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,        // VkStructureType                                                      sType;
@@ -602,6 +604,7 @@ vk::Move<vk::VkPipeline> makeGraphicsPipeline (const vk::DeviceInterface&           vk,
                topology,                                                                                                                       // VkPrimitiveTopology                                          topology;
                VK_FALSE                                                                                                                        // VkBool32                                                                     primitiveRestartEnable;
        };
+
        const vk::VkViewport                                                            viewport                                        =
        {
                0.0f,                                           // float        originX;
@@ -611,11 +614,13 @@ vk::Move<vk::VkPipeline> makeGraphicsPipeline (const vk::DeviceInterface&         vk,
                0.0f,                                           // float        minDepth;
                1.0f                                            // float        maxDepth;
        };
+
        const vk::VkRect2D                                                                      scissor                                         =
        {
                { 0, 0 },                                                               // VkOffset2D   offset;
                { renderSize.x(), renderSize.y() }              // VkExtent2D   extent;
        };
+
        const vk::VkPipelineViewportStateCreateInfo                     viewportStateParams                     =
        {
                vk::VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,              // VkStructureType                                              sType;
@@ -626,6 +631,7 @@ vk::Move<vk::VkPipeline> makeGraphicsPipeline (const vk::DeviceInterface&           vk,
                1u,                                                                                                                             // deUint32                                                             scissorsCount;
                &scissor,                                                                                                               // const VkRect2D*                                              pScissors;
        };
+
        const vk::VkPipelineRasterizationStateCreateInfo        rasterStateParams                       =
        {
                vk::VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType                                                      sType;
@@ -642,6 +648,7 @@ vk::Move<vk::VkPipeline> makeGraphicsPipeline (const vk::DeviceInterface&           vk,
                0.0f,                                                                                                                   // float                                                                        slopeScaledDepthBias;
                1.0f,                                                                                                                   // float                                                                        lineWidth;
        };
+
        const vk::VkPipelineMultisampleStateCreateInfo          multisampleStateParams          =
        {
                vk::VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,   // VkStructureType                                                      sType;
@@ -654,6 +661,7 @@ vk::Move<vk::VkPipeline> makeGraphicsPipeline (const vk::DeviceInterface&           vk,
                VK_FALSE,                                                                                                               // VkBool32                                                                     alphaToCoverageEnable;
                VK_FALSE                                                                                                                // VkBool32                                                                     alphaToOneEnable;
        };
+
        const vk::VkPipelineColorBlendAttachmentState           colorBlendAttachmentState       =
        {
                VK_FALSE,                                                                                                               // VkBool32                     blendEnable;
@@ -668,6 +676,7 @@ vk::Move<vk::VkPipeline> makeGraphicsPipeline (const vk::DeviceInterface&           vk,
                 vk::VK_COLOR_COMPONENT_B_BIT |
                 vk::VK_COLOR_COMPONENT_A_BIT),                                                                 // VkChannelFlags       channelWriteMask;
        };
+
        const vk::VkPipelineColorBlendStateCreateInfo           colorBlendStateParams           =
        {
                vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,   // VkStructureType                                                              sType;
@@ -679,6 +688,7 @@ vk::Move<vk::VkPipeline> makeGraphicsPipeline (const vk::DeviceInterface&           vk,
                &colorBlendAttachmentState,                                                                             // const VkPipelineColorBlendAttachmentState*   pAttachments;
                { 0.0f, 0.0f, 0.0f, 0.0f },                                                                             // float                                                                                blendConst[4];
        };
+
        const vk::VkGraphicsPipelineCreateInfo                          graphicsPipelineParams          =
        {
                vk::VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,                    // VkStructureType                                                                      sType;
@@ -701,6 +711,7 @@ vk::Move<vk::VkPipeline> makeGraphicsPipeline (const vk::DeviceInterface&           vk,
                0u,                                                                                                                             // VkPipeline                                                                           basePipelineHandle;
                0u                                                                                                                              // deInt32                                                                                      basePipelineIndex;
        };
+
        return vk::createGraphicsPipeline(vk, device, DE_NULL, &graphicsPipelineParams);
 }
 
@@ -715,6 +726,5 @@ const char* getCmdBufferTypeStr (const CmdBufferType cmdBufferType)
        }
 }
 
-
 } // ProtectedMem
 } // vkt
index 44c8241..0cf2ca2 100644 (file)
@@ -140,6 +140,17 @@ vk::Move<vk::VkPipeline>                   makeGraphicsPipeline                            (const vk::DeviceInterface&
                                                                                                                                                 const tcu::UVec2&                                      renderSize,
                                                                                                                                                 const vk::VkPrimitiveTopology          topology);
 
+vk::Move<vk::VkPipeline>                       makeGraphicsPipeline                            (const vk::DeviceInterface&                     vk,
+                                                                                                                                                const vk::VkDevice                                     device,
+                                                                                                                                                const vk::VkPipelineLayout                     pipelineLayout,
+                                                                                                                                                const vk::VkRenderPass                         renderPass,
+                                                                                                                                                const vk::VkShaderModule                       vertexShaderModule,
+                                                                                                                                                const vk::VkShaderModule                       fragmentShaderModule,
+                                                                                                                                                const VertexBindings&                          vertexBindings,
+                                                                                                                                                const VertexAttribs&                           vertexAttribs,
+                                                                                                                                                const tcu::UVec2&                                      renderSize,
+                                                                                                                                                const vk::VkPrimitiveTopology          topology);
+
 } // ProtectedMem
 } // vkt
 
index 145c883..7994f48 100755 (executable)
@@ -265760,6 +265760,55 @@ dEQP-VK.protected_memory.image.copy_buffer_to_image.secondary.random.copy_7
 dEQP-VK.protected_memory.image.copy_buffer_to_image.secondary.random.copy_8
 dEQP-VK.protected_memory.image.copy_buffer_to_image.secondary.random.copy_9
 dEQP-VK.protected_memory.image.copy_buffer_to_image.secondary.random.copy_10
+dEQP-VK.protected_memory.image.access.fragment.sampling.rgba8
+dEQP-VK.protected_memory.image.access.fragment.sampling.r32i
+dEQP-VK.protected_memory.image.access.fragment.sampling.r32ui
+dEQP-VK.protected_memory.image.access.fragment.texelfetch.rgba8
+dEQP-VK.protected_memory.image.access.fragment.texelfetch.r32i
+dEQP-VK.protected_memory.image.access.fragment.texelfetch.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imageload.rgba8
+dEQP-VK.protected_memory.image.access.fragment.imageload.r32i
+dEQP-VK.protected_memory.image.access.fragment.imageload.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imagestore.rgba8
+dEQP-VK.protected_memory.image.access.fragment.imagestore.r32i
+dEQP-VK.protected_memory.image.access.fragment.imagestore.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.add.r32i
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.add.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.min.r32i
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.min.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.max.r32i
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.max.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.and.r32i
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.and.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.or.r32i
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.or.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.xor.r32i
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.xor.r32ui
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.exchange.r32i
+dEQP-VK.protected_memory.image.access.fragment.imageatomics.exchange.r32ui
+dEQP-VK.protected_memory.image.access.compute.sampling.rgba8
+dEQP-VK.protected_memory.image.access.compute.sampling.r32i
+dEQP-VK.protected_memory.image.access.compute.sampling.r32ui
+dEQP-VK.protected_memory.image.access.compute.texelfetch.rgba8
+dEQP-VK.protected_memory.image.access.compute.texelfetch.r32i
+dEQP-VK.protected_memory.image.access.compute.texelfetch.r32ui
+dEQP-VK.protected_memory.image.access.compute.imageload.rgba8
+dEQP-VK.protected_memory.image.access.compute.imageload.r32i
+dEQP-VK.protected_memory.image.access.compute.imageload.r32ui
+dEQP-VK.protected_memory.image.access.compute.imageatomics.add.r32i
+dEQP-VK.protected_memory.image.access.compute.imageatomics.add.r32ui
+dEQP-VK.protected_memory.image.access.compute.imageatomics.min.r32i
+dEQP-VK.protected_memory.image.access.compute.imageatomics.min.r32ui
+dEQP-VK.protected_memory.image.access.compute.imageatomics.max.r32i
+dEQP-VK.protected_memory.image.access.compute.imageatomics.max.r32ui
+dEQP-VK.protected_memory.image.access.compute.imageatomics.and.r32i
+dEQP-VK.protected_memory.image.access.compute.imageatomics.and.r32ui
+dEQP-VK.protected_memory.image.access.compute.imageatomics.or.r32i
+dEQP-VK.protected_memory.image.access.compute.imageatomics.or.r32ui
+dEQP-VK.protected_memory.image.access.compute.imageatomics.xor.r32i
+dEQP-VK.protected_memory.image.access.compute.imageatomics.xor.r32ui
+dEQP-VK.protected_memory.image.access.compute.imageatomics.exchange.r32i
+dEQP-VK.protected_memory.image.access.compute.imageatomics.exchange.r32ui
 dEQP-VK.protected_memory.buffer.fill.float_buffer.primary.static.test_1
 dEQP-VK.protected_memory.buffer.fill.float_buffer.primary.static.test_2
 dEQP-VK.protected_memory.buffer.fill.float_buffer.primary.static.test_3