Add tests for descriptor copy
authorAri Suonpaa <ari.suonpaa@siru.fi>
Wed, 9 Jan 2019 05:32:13 +0000 (07:32 +0200)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Thu, 14 Feb 2019 15:23:52 +0000 (10:23 -0500)
Added a test for copying descriptors. The test
uses a list of commands for declaring different
descriptor types and performing copies between
the descriptors. Descriptor arrays and dynamic
offsets are also tested.

New tests:

dEQP-VK.binding_model.descriptor_copy.*

Components: Vulkan

VK-GL-CTS issue: 1497
Change-Id: Iffae93873e022d2532fc495bb57f9ae467b6d195

AndroidGen.mk
android/cts/master/vk-master.txt
external/vulkancts/modules/vulkan/binding_model/CMakeLists.txt
external/vulkancts/modules/vulkan/binding_model/vktBindingDescriptorCopyTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/binding_model/vktBindingDescriptorCopyTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/binding_model/vktBindingModelTests.cpp
external/vulkancts/mustpass/1.1.4/vk-default-no-waivers.txt
external/vulkancts/mustpass/1.1.4/vk-default.txt

index 9307349..12c15b7 100644 (file)
@@ -82,6 +82,7 @@ LOCAL_SRC_FILES := \
        external/vulkancts/modules/vulkan/api/vktApiSmokeTests.cpp \
        external/vulkancts/modules/vulkan/api/vktApiTests.cpp \
        external/vulkancts/modules/vulkan/api/vktApiVersionCheck.cpp \
+       external/vulkancts/modules/vulkan/binding_model/vktBindingDescriptorCopyTests.cpp \
        external/vulkancts/modules/vulkan/binding_model/vktBindingDescriptorSetRandomTests.cpp \
        external/vulkancts/modules/vulkan/binding_model/vktBindingDescriptorUpdateTests.cpp \
        external/vulkancts/modules/vulkan/binding_model/vktBindingModelTests.cpp \
index 425be0d..61d33e2 100755 (executable)
@@ -222905,6 +222905,193 @@ dEQP-VK.binding_model.descriptorset_random.sets32.runtimesize.ubolimithigh.sboli
 dEQP-VK.binding_model.descriptorset_random.sets32.runtimesize.ubolimithigh.sbolimithigh.imglimithigh.iublimithigh.comp.0
 dEQP-VK.binding_model.descriptorset_random.sets32.runtimesize.ubolimithigh.sbolimithigh.imglimithigh.iublimithigh.frag.0
 dEQP-VK.binding_model.descriptorset_random.sets32.runtimesize.ubolimithigh.sbolimithigh.imglimithigh.iublimithigh.vert.0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_2
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_3
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_4
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_5
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_6
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_3
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_4
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_5
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_6
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_0
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_1
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_2
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_3
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_4
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_5
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_6
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_array0
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_array1
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_array2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_3
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_4
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_5
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_6
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_array0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_array1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_array2
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_2
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_3
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_4
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_5
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_6
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_3
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_4
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_5
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_6
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_2
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_3
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_4
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_5
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_6
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_array0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_array1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_array2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_3
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_4
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_5
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_6
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_array0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_array1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_array2
+dEQP-VK.binding_model.descriptor_copy.compute.sampler_0
+dEQP-VK.binding_model.descriptor_copy.compute.sampler_array0
+dEQP-VK.binding_model.descriptor_copy.compute.sampler_array1
+dEQP-VK.binding_model.descriptor_copy.compute.sampled_image_0
+dEQP-VK.binding_model.descriptor_copy.compute.sampled_image_array0
+dEQP-VK.binding_model.descriptor_copy.compute.mix_0
+dEQP-VK.binding_model.descriptor_copy.compute.mix_1
+dEQP-VK.binding_model.descriptor_copy.compute.mix_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_2
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_3
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_4
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_5
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_6
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_3
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_4
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_5
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_6
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_0
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_1
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_2
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_3
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_4
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_5
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_6
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_3
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_4
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_5
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_6
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_0
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_1
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_2
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_3
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_4
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_5
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_6
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_2
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_3
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_4
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_5
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_6
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_3
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_4
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_5
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_6
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_2
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_3
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_4
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_5
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_6
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_3
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_4
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_5
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_6
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.sampler_0
+dEQP-VK.binding_model.descriptor_copy.graphics.sampler_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.sampler_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.sampled_image_0
+dEQP-VK.binding_model.descriptor_copy.graphics.sampled_image_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.mix_0
+dEQP-VK.binding_model.descriptor_copy.graphics.mix_1
+dEQP-VK.binding_model.descriptor_copy.graphics.mix_2
+dEQP-VK.binding_model.descriptor_copy.graphics.mix_array0
 dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_0_compute
 dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_1_compute
 dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_2_compute
index 6de4b7b..2f5a793 100644 (file)
@@ -11,6 +11,8 @@ set(DEQP_VK_BINDING_MODEL_SRCS
        vktBindingDescriptorUpdateTests.hpp
        vktBindingDescriptorSetRandomTests.cpp
        vktBindingDescriptorSetRandomTests.hpp
+       vktBindingDescriptorCopyTests.cpp
+       vktBindingDescriptorCopyTests.hpp
        )
 
 set(DEQP_VK_BINDING_MODEL_LIBS
diff --git a/external/vulkancts/modules/vulkan/binding_model/vktBindingDescriptorCopyTests.cpp b/external/vulkancts/modules/vulkan/binding_model/vktBindingDescriptorCopyTests.cpp
new file mode 100644 (file)
index 0000000..2876be7
--- /dev/null
@@ -0,0 +1,2703 @@
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2019 Google Inc.
+ * Copyright (c) 2019 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Tests for descriptor copying
+ *//*--------------------------------------------------------------------*/
+
+#include "vktBindingDescriptorCopyTests.hpp"
+
+#include "vkBufferWithMemory.hpp"
+#include "vkImageWithMemory.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkCmdUtil.hpp"
+#include "vkTypeUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkObjUtil.hpp"
+#include "vktTestGroupUtil.hpp"
+#include "vktTestCase.hpp"
+
+#include "deDefs.h"
+#include "deMath.h"
+#include "deRandom.h"
+#include "deSharedPtr.hpp"
+#include "deString.h"
+
+#include "tcuTestCase.hpp"
+#include "tcuTestLog.hpp"
+
+#include <string>
+#include <sstream>
+
+namespace vkt
+{
+namespace BindingModel
+{
+namespace
+{
+using namespace vk;
+using namespace std;
+using tcu::Vec4;
+using tcu::Vec2;
+
+enum PipelineType
+{
+       PIPELINE_TYPE_COMPUTE = 0,
+       PIPELINE_TYPE_GRAPHICS = 1
+};
+
+struct DescriptorCopy
+{
+       deUint32        srcSet;
+       deUint32        srcBinding;
+       deUint32        srcArrayElement;
+       deUint32        dstSet;
+       deUint32        dstBinding;
+       deUint32        dstArrayElement;
+       deUint32        descriptorCount;
+};
+
+struct DescriptorData
+{
+       vector<deUint32>        data;           // The actual data. One element per dynamic offset.
+       bool                            written;        // Is the data written in descriptor update
+       bool                            copiedInto;     // Is the data being overwritten by a copy operation
+};
+
+typedef de::SharedPtr<ImageWithMemory>                                 ImageWithMemorySp;
+typedef de::SharedPtr<Unique<VkImageView> >                            VkImageViewSp;
+typedef de::SharedPtr<Unique<VkBufferView> >                   VkBufferViewSp;
+typedef de::SharedPtr<Unique<VkSampler> >                              VkSamplerSp;
+typedef de::SharedPtr<Unique<VkDescriptorSetLayout> >  VkDescriptorSetLayoutSp;
+
+const tcu::IVec2 renderSize(64, 64);
+
+// Base class for descriptors
+class Descriptor
+{
+public:
+                                                                                       Descriptor                              (VkDescriptorType descriptorType, deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u);
+       virtual                                                                 ~Descriptor                             (void);
+       VkDescriptorType                                                getType                                 (void) const { return m_descriptorType; }
+       deUint32                                                                getArraySize                    (void) const { return m_arraySize; }
+       virtual VkWriteDescriptorSet                    getDescriptorWrite              (void) = 0;
+       virtual string                                                  getShaderDeclaration    (void) const = 0;
+       virtual void                                                    init                                    (Context& context, PipelineType pipelineType) = 0;
+       virtual void                                                    copyValue                               (const Descriptor& src, deUint32 srcElement, deUint32 dstElement, deUint32 numElements);
+       virtual void                                                    invalidate                              (Context& context) { DE_UNREF(context); }
+       virtual vector<deUint32>                                getData                                 (void) { DE_FATAL("Unexpected"); return vector<deUint32>(); }
+       deUint32                                                                getId                                   (void) const { return m_id; }
+       virtual string                                                  getShaderVerifyCode             (void) const = 0;
+       string                                                                  getArrayString                  (deUint32 index) const;
+       deUint32                                                                getFirstWrittenElement  (void) const;
+       deUint32                                                                getNumWrittenElements   (void) const;
+       deUint32                                                                getReferenceData                (deUint32 arrayIdx, deUint32 dynamicAreaIdx = 0) const { return m_data[arrayIdx].data[dynamicAreaIdx]; }
+       virtual bool                                                    isDynamic                               (void) const { return false; }
+       virtual void                                                    setDynamicAreas                 (vector<deUint32> dynamicAreas) { DE_UNREF(dynamicAreas); }
+       virtual vector<VkImageViewSp>                   getImageViews                   (void) const { return vector<VkImageViewSp>(); }
+       virtual vector<VkAttachmentReference>   getAttachmentReferences (void) const { return vector<VkAttachmentReference>(); }
+
+       static deUint32                                                 s_nextId;
+protected:
+       VkDescriptorType                                                m_descriptorType;
+       deUint32                                                                m_arraySize;
+       deUint32                                                                m_id;
+       vector<DescriptorData>                                  m_data;
+       deUint32                                                                m_numDynamicAreas;
+};
+
+typedef de::SharedPtr<Descriptor>      DescriptorSp;
+
+// Base class for all buffer based descriptors
+class BufferDescriptor : public Descriptor
+{
+public:
+                                                                       BufferDescriptor                (VkDescriptorType type, deUint32 arraySize, deUint32 writeStart, deUint32 elementsToWrite, deUint32 numDynamicAreas = 1u);
+       virtual                                                 ~BufferDescriptor               (void);
+       void                                                    init                                    (Context& context, PipelineType pipelineType);
+
+       VkWriteDescriptorSet                    getDescriptorWrite              (void);
+       virtual string                                  getShaderDeclaration    (void) const = 0;
+       void                                                    invalidate                              (Context& context);
+       vector<deUint32>                                getData                                 (void);
+       virtual string                                  getShaderVerifyCode             (void) const = 0;
+       virtual VkBufferUsageFlags              getBufferUsageFlags             (void) const = 0;
+       virtual bool                                    usesBufferView                  (void) { return false; }
+private:
+       vector<VkDescriptorBufferInfo>  m_descriptorBufferInfos;
+       de::MovePtr<BufferWithMemory>   m_buffer;
+       deUint32                                                m_bufferSize;
+       vector<VkBufferViewSp>                  m_bufferViews;
+       vector<VkBufferView>                    m_bufferViewHandles;
+};
+
+class UniformBufferDescriptor : public BufferDescriptor
+{
+public:
+                                               UniformBufferDescriptor         (deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u);
+       virtual                         ~UniformBufferDescriptor        (void);
+
+       string                          getShaderDeclaration            (void) const;
+       string                          getShaderVerifyCode                     (void) const;
+       VkBufferUsageFlags      getBufferUsageFlags                     (void) const { return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; }
+private:
+};
+
+class DynamicUniformBufferDescriptor : public BufferDescriptor
+{
+public:
+                                               DynamicUniformBufferDescriptor  (deUint32 arraySize, deUint32 writeStart, deUint32 elementsToWrite, deUint32 numDynamicAreas);
+       virtual                         ~DynamicUniformBufferDescriptor (void);
+
+       string                          getShaderDeclaration                    (void) const;
+       string                          getShaderVerifyCode                             (void) const;
+       VkBufferUsageFlags      getBufferUsageFlags                             (void) const { return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; }
+       virtual void            setDynamicAreas                                 (vector<deUint32> dynamicAreas) { m_dynamicAreas = dynamicAreas; }
+       virtual bool            isDynamic                                               (void) const { return true; }
+
+private:
+       vector<deUint32>        m_dynamicAreas;
+};
+
+class StorageBufferDescriptor : public BufferDescriptor
+{
+public:
+                                               StorageBufferDescriptor         (deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u);
+       virtual                         ~StorageBufferDescriptor        (void);
+
+       string                          getShaderDeclaration            (void) const;
+       string                          getShaderVerifyCode                     (void) const;
+       VkBufferUsageFlags      getBufferUsageFlags                     (void) const { return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; }
+private:
+};
+
+class DynamicStorageBufferDescriptor : public BufferDescriptor
+{
+public:
+                                               DynamicStorageBufferDescriptor  (deUint32 arraySize, deUint32 writeStart, deUint32 elementsToWrite, deUint32 numDynamicAreas);
+       virtual                         ~DynamicStorageBufferDescriptor (void);
+
+       string                          getShaderDeclaration                    (void) const;
+       string                          getShaderVerifyCode                             (void) const;
+       VkBufferUsageFlags      getBufferUsageFlags                             (void) const { return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; }
+       virtual void            setDynamicAreas                                 (vector<deUint32> dynamicAreas) { m_dynamicAreas = dynamicAreas; }
+       virtual bool            isDynamic                                               (void) const { return true; }
+
+private:
+       vector<deUint32>        m_dynamicAreas;
+};
+
+class UniformTexelBufferDescriptor : public BufferDescriptor
+{
+public:
+                                               UniformTexelBufferDescriptor    (deUint32 arraySize = 1, deUint32 writeStart = 0, deUint32 elementsToWrite = 1, deUint32 numDynamicAreas = 1);
+       virtual                         ~UniformTexelBufferDescriptor   (void);
+
+       string                          getShaderDeclaration                    (void) const;
+       string                          getShaderVerifyCode                             (void) const;
+       VkBufferUsageFlags      getBufferUsageFlags                             (void) const { return VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT; }
+       bool                            usesBufferView                                  (void) { return true; }
+private:
+};
+
+class StorageTexelBufferDescriptor : public BufferDescriptor
+{
+public:
+                                               StorageTexelBufferDescriptor    (deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u);
+       virtual                         ~StorageTexelBufferDescriptor   (void);
+
+       string                          getShaderDeclaration                    (void) const;
+       string                          getShaderVerifyCode                             (void) const;
+       VkBufferUsageFlags      getBufferUsageFlags                             (void) const { return VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; }
+       bool                            usesBufferView                                  (void) { return true; }
+private:
+};
+
+// Base class for all image based descriptors
+class ImageDescriptor : public Descriptor
+{
+public:
+                                                                       ImageDescriptor                 (VkDescriptorType type, deUint32 arraySize, deUint32 writeStart, deUint32 elementsToWrite, deUint32 numDynamicAreas);
+       virtual                                                 ~ImageDescriptor                (void);
+       void                                                    init                                    (Context& context, PipelineType pipelineType);
+
+       VkWriteDescriptorSet                    getDescriptorWrite              (void);
+       virtual VkImageUsageFlags               getImageUsageFlags              (void) const = 0;
+       virtual string                                  getShaderDeclaration    (void) const = 0;
+       virtual string                                  getShaderVerifyCode             (void) const = 0;
+       virtual VkAccessFlags                   getAccessFlags                  (void) const { return VK_ACCESS_SHADER_READ_BIT; }
+       virtual VkImageLayout                   getImageLayout                  (void) const { return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; }
+
+protected:
+       vector<VkImageViewSp>                   m_imageViews;
+
+private:
+       vector<ImageWithMemorySp>               m_images;
+       vector<VkDescriptorImageInfo>   m_descriptorImageInfos;
+       Move<VkSampler>                                 m_sampler;
+};
+
+class InputAttachmentDescriptor : public ImageDescriptor
+{
+public:
+                                                                       InputAttachmentDescriptor       (deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u);
+       virtual                                                 ~InputAttachmentDescriptor      (void);
+
+       VkImageUsageFlags                               getImageUsageFlags                      (void) const { return VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; }
+       string                                                  getShaderDeclaration            (void) const;
+       string                                                  getShaderVerifyCode                     (void) const;
+       vector<VkImageViewSp>                   getImageViews                           (void) const { return m_imageViews; }
+       void                                                    copyValue                                       (const Descriptor& src, deUint32 srcElement, deUint32 dstElement, deUint32 numElements);
+       VkAccessFlags                                   getAccessFlags                          (void) const { return VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; }
+       vector<VkAttachmentReference>   getAttachmentReferences         (void) const;
+       static deUint32                                 s_nextAttachmentIndex;
+private:
+       vector<deUint32>                                m_attachmentIndices;
+       deUint32                                                m_originalAttachmentIndex;
+};
+
+class CombinedImageSamplerDescriptor : public ImageDescriptor
+{
+public:
+                                               CombinedImageSamplerDescriptor  (deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u);
+       virtual                         ~CombinedImageSamplerDescriptor (void);
+
+       VkImageUsageFlags       getImageUsageFlags                              (void) const { return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; }
+       string                          getShaderDeclaration                    (void) const;
+       string                          getShaderVerifyCode                             (void) const;
+private:
+};
+
+class SamplerDescriptor;
+
+class SampledImageDescriptor : public ImageDescriptor
+{
+public:
+                                                               SampledImageDescriptor  (deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u);
+       virtual                                         ~SampledImageDescriptor (void);
+
+       VkImageUsageFlags                       getImageUsageFlags              (void) const { return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; }
+       string                                          getShaderDeclaration    (void) const;
+       string                                          getShaderVerifyCode             (void) const;
+       void                                            addSampler                              (SamplerDescriptor* sampler, deUint32 count = 1u) { for (deUint32 i = 0; i < count; i++) m_samplers.push_back(sampler); }
+private:
+       vector<SamplerDescriptor*>      m_samplers;
+};
+
+class SamplerDescriptor : public Descriptor
+{
+public:
+                                                                       SamplerDescriptor               (deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u);
+       virtual                                                 ~SamplerDescriptor              (void);
+       void                                                    init                                    (Context& context, PipelineType pipelineType);
+
+       void                                                    addImage                                (SampledImageDescriptor* image, deUint32 count = 1u) { for (deUint32 i = 0; i < count; i++ ) m_images.push_back(image); }
+       VkWriteDescriptorSet                    getDescriptorWrite              (void);
+       string                                                  getShaderDeclaration    (void) const;
+       string                                                  getShaderVerifyCode             (void) const;
+
+private:
+       vector<VkSamplerSp>                             m_samplers;
+       vector<VkDescriptorImageInfo>   m_descriptorImageInfos;
+       vector<SampledImageDescriptor*> m_images;
+};
+
+class StorageImageDescriptor : public ImageDescriptor
+{
+public:
+                                               StorageImageDescriptor  (deUint32 arraySize = 1u, deUint32 writeStart = 0u, deUint32 elementsToWrite = 1u, deUint32 numDynamicAreas = 1u);
+       virtual                         ~StorageImageDescriptor (void);
+
+       VkImageUsageFlags       getImageUsageFlags              (void) const { return VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; }
+       string                          getShaderDeclaration    (void) const;
+       string                          getShaderVerifyCode             (void) const;
+       VkImageLayout           getImageLayout                  (void) const { return VK_IMAGE_LAYOUT_GENERAL; }
+private:
+};
+
+class DescriptorSet
+{
+public:
+                                                               DescriptorSet   (void);
+                                                               ~DescriptorSet  (void);
+       void                                            addBinding              (DescriptorSp descriptor);
+       const vector<DescriptorSp>      getBindings             (void) const { return m_bindings; }
+
+private:
+       vector<DescriptorSp>            m_bindings;
+};
+
+typedef de::SharedPtr<DescriptorSet> DescriptorSetSp;
+
+// Class that handles descriptor sets and descriptors bound to those sets. Keeps track of copy operations.
+class DescriptorCommands
+{
+public:
+                                       DescriptorCommands                      (PipelineType pipelineType);
+                                       ~DescriptorCommands                     (void);
+       void                    addDescriptor                           (DescriptorSp descriptor, deUint32 descriptorSet);
+       void                    copyDescriptor                          (deUint32 srcSet, deUint32 srcBinding, deUint32 srcArrayElement, deUint32 dstSet, deUint32 dstBinding, deUint32 dstArrayElement, deUint32 descriptorCount);
+       void                    copyDescriptor                          (deUint32 srcSet, deUint32 srcBinding, deUint32 dstSet, deUint32 dstBinding) { copyDescriptor(srcSet, srcBinding, 0u, dstSet, dstBinding, 0u, 1u); }
+       string                  getShaderDeclarations           (void) const;
+       string                  getDescriptorVerifications      (void) const;
+       void                    addResultBuffer                         (void);
+       deUint32                getResultBufferId                       (void) const { return m_resultBuffer->getId(); }
+       void                    setDynamicAreas                         (vector<deUint32> areas);
+       bool                    hasDynamicAreas                         (void) const;
+       PipelineType    getPipelineType                         (void) const { return m_pipelineType; }
+
+       tcu::TestStatus run(Context& context);
+
+private:
+       PipelineType                                    m_pipelineType;
+       vector<DescriptorSetSp>                 m_descriptorSets;
+       vector<DescriptorCopy>                  m_descriptorCopies;
+       vector<DescriptorSp>                    m_descriptors;
+       map<VkDescriptorType, deUint32> m_descriptorCounts;
+       DescriptorSp                                    m_resultBuffer;
+       vector<deUint32>                                m_dynamicAreas;
+};
+
+typedef de::SharedPtr<DescriptorCommands> DescriptorCommandsSp;
+
+class DescriptorCopyTestInstance : public TestInstance
+{
+public:
+                                                       DescriptorCopyTestInstance      (Context& context, DescriptorCommandsSp commands);
+                                                       ~DescriptorCopyTestInstance     (void);
+       tcu::TestStatus                 iterate                                         (void);
+private:
+       DescriptorCommandsSp    m_commands;
+};
+
+class DescriptorCopyTestCase : public TestCase
+{
+       public:
+                                                       DescriptorCopyTestCase  (tcu::TestContext& context, const char* name, const char* desc, DescriptorCommandsSp commands);
+       virtual                                 ~DescriptorCopyTestCase (void);
+       virtual void                    initPrograms                    (SourceCollections& programCollection) const;
+       virtual TestInstance*   createInstance                  (Context& context) const;
+
+private:
+       DescriptorCommandsSp    m_commands;
+};
+
+deUint32 Descriptor::s_nextId = 0xabc; // Random starting point for ID counter
+deUint32 InputAttachmentDescriptor::s_nextAttachmentIndex = 0;
+
+Descriptor::Descriptor (VkDescriptorType       descriptorType,
+                                               deUint32                        arraySize,
+                                               deUint32                        writeStart,
+                                               deUint32                        elementsToWrite,
+                                               deUint32                        numDynamicAreas)
+: m_descriptorType(descriptorType)
+, m_arraySize(arraySize)
+, m_id(s_nextId++)
+, m_numDynamicAreas(numDynamicAreas)
+{
+       for (deUint32 arrayIdx = 0; arrayIdx < m_arraySize; arrayIdx++)
+       {
+               const bool                              written                 = arrayIdx >= writeStart && arrayIdx < writeStart + elementsToWrite;
+               vector<deUint32>                data;
+
+               for (deUint32 dynamicAreaIdx = 0; dynamicAreaIdx < m_numDynamicAreas; dynamicAreaIdx++)
+                       data.push_back(m_id + arrayIdx * m_numDynamicAreas + dynamicAreaIdx);
+
+               const DescriptorData    descriptorData  =
+               {
+                       data,           // vector<deUint32>     data
+                       written,        // bool                         written
+                       false           // bool                         copiedInto
+               };
+
+               m_data.push_back(descriptorData);
+       }
+}
+
+Descriptor::~Descriptor (void)
+{
+}
+
+// Copy refrence data from another descriptor
+void Descriptor::copyValue (const Descriptor&  src,
+                                                       deUint32                        srcElement,
+                                                       deUint32                        dstElement,
+                                                       deUint32                        numElements)
+{
+       for (deUint32 elementIdx = 0; elementIdx < numElements; elementIdx++)
+       {
+               DE_ASSERT(src.m_data[elementIdx + srcElement].written);
+
+               for (deUint32 dynamicAreaIdx = 0; dynamicAreaIdx < de::min(m_numDynamicAreas, src.m_numDynamicAreas); dynamicAreaIdx++)
+                       m_data[elementIdx + dstElement].data[dynamicAreaIdx] = src.m_data[elementIdx + srcElement].data[dynamicAreaIdx];
+
+               m_data[elementIdx + dstElement].copiedInto = true;
+       }
+}
+
+string Descriptor::getArrayString (deUint32 index) const
+{
+       return m_arraySize > 1 ? (string("[") + de::toString(index) + "]") : "";
+}
+
+// Returns the first element to be written in descriptor update
+deUint32 Descriptor::getFirstWrittenElement (void) const
+{
+       for (deUint32 i = 0; i < (deUint32)m_data.size(); i++)
+               if (m_data[i].written)
+                       return i;
+
+       return 0;
+}
+
+// Returns the number of array elements to be written for a descriptor array
+deUint32 Descriptor::getNumWrittenElements (void) const
+{
+       deUint32        numElements = 0;
+
+       for (deUint32 i = 0; i < (deUint32)m_data.size(); i++)
+               if (m_data[i].written)
+                       numElements++;
+
+       return numElements;
+}
+
+BufferDescriptor::BufferDescriptor (VkDescriptorType   type,
+                                                                       deUint32                        arraySize,
+                                                                       deUint32                        writeStart,
+                                                                       deUint32                        elementsToWrite,
+                                                                       deUint32                        numDynamicAreas)
+: Descriptor(type, arraySize, writeStart, elementsToWrite, numDynamicAreas)
+, m_bufferSize(256u * arraySize * numDynamicAreas)
+{
+}
+
+BufferDescriptor::~BufferDescriptor (void)
+{
+}
+
+void BufferDescriptor::init (Context&          context,
+                                                        PipelineType   pipelineType)
+{
+       DE_UNREF(pipelineType);
+
+       const DeviceInterface&          vk                      = context.getDeviceInterface();
+    const VkDevice                             device          = context.getDevice();
+    Allocator&                                 allocator       = context.getDefaultAllocator();
+
+       // Create buffer
+       {
+               const VkBufferCreateInfo        bufferCreateInfo        =
+               {
+                       VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // VkStructureType              sType
+                       DE_NULL,                                                                // const void*                  pNext
+                       0u,                                                                             // VkBufferCreateFlags  flags
+                       m_bufferSize,                                                   // VkDeviceSize                 size
+                       getBufferUsageFlags(),                                  // VkBufferUsageFlags   usage
+                       VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode                sharingMode
+                       0u,                                                                             // uint32_t                             queueFamilyIndexCount
+                       DE_NULL                                                                 // const uint32_t*              pQueueFamilyIndices
+               };
+
+               m_buffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
+       }
+
+       // Create descriptor buffer infos
+       {
+               for (deUint32 arrayIdx = 0; arrayIdx < m_arraySize; arrayIdx++)
+               {
+                       const VkDescriptorBufferInfo bufferInfo =
+                       {
+                               m_buffer->get(),                                                // VkBuffer             buffer
+                               256u * m_numDynamicAreas * arrayIdx,    // VkDeviceSize offset
+                               isDynamic() ? 256u : 4u                                 // VkDeviceSize range
+                       };
+
+                       m_descriptorBufferInfos.push_back(bufferInfo);
+               }
+       }
+
+       // Create buffer views
+       if (usesBufferView())
+       {
+               for (deUint32 viewIdx = 0; viewIdx < m_arraySize; viewIdx++)
+               {
+                       const VkBufferViewCreateInfo bufferViewCreateInfo =
+                       {
+                               VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,      // VkStructureType                      sType
+                               DE_NULL,                                                                        // const void*                          pNext
+                               0u,                                                                                     // VkBufferViewCreateFlags      flags
+                               m_buffer->get(),                                                        // VkBuffer                                     buffer
+                               VK_FORMAT_R32_SFLOAT,                                           // VkFormat                                     format
+                               256u * viewIdx,                                                         // VkDeviceSize                         offset
+                               4u                                                                                      // VkDeviceSize                         range
+                       };
+
+                       m_bufferViews.push_back(VkBufferViewSp(new Unique<VkBufferView>(createBufferView(vk, device, &bufferViewCreateInfo))));
+                       m_bufferViewHandles.push_back(**m_bufferViews[viewIdx]);
+               }
+       }
+
+       // Initialize buffer memory
+       {
+               deUint32* hostPtr = (deUint32*)m_buffer->getAllocation().getHostPtr();
+
+               for (deUint32 arrayIdx = 0; arrayIdx < m_arraySize; arrayIdx++)
+               {
+                       for (deUint32 dynamicAreaIdx = 0; dynamicAreaIdx < m_numDynamicAreas; dynamicAreaIdx++)
+                       {
+                               union BufferValue
+                               {
+                                       deUint32        uintValue;
+                                       float           floatValue;
+                               } bufferValue;
+
+                               bufferValue.uintValue = m_id + (arrayIdx * m_numDynamicAreas) + dynamicAreaIdx;
+
+                               if (usesBufferView())
+                                       bufferValue.floatValue = (float)bufferValue.uintValue;
+
+                               hostPtr[(256 / 4) * (m_numDynamicAreas * arrayIdx + dynamicAreaIdx)] = bufferValue.uintValue;
+                       }
+               }
+
+               flushMappedMemoryRange(vk, device, m_buffer->getAllocation().getMemory(), m_buffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
+       }
+}
+
+VkWriteDescriptorSet BufferDescriptor::getDescriptorWrite (void)
+{
+       const deUint32                          firstElement    = getFirstWrittenElement();
+
+       // Set and binding will be overwritten later
+       const VkWriteDescriptorSet      descriptorWrite =
+       {
+               VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,                                                                 // VkStructureType                                      sType
+               DE_NULL,                                                                                                                                // const void*                                          pNext
+               (VkDescriptorSet)0u,                                                                                                    // VkDescriptorSet                                      dstSet
+               0u,                                                                                                                                             // deUint32                                                     dstBinding
+               firstElement,                                                                                                                   // deUint32                                                     dstArrayElement
+               getNumWrittenElements(),                                                                                                // deUint32                                                     descriptorCount
+               getType(),                                                                                                                              // VkDescriptorType                                     descriptorType
+               DE_NULL,                                                                                                                                // const VkDescriptorImageInfo          pImageInfo
+               usesBufferView() ? DE_NULL : &m_descriptorBufferInfos[firstElement],    // const VkDescriptorBufferInfo*        pBufferInfo
+               usesBufferView() ? &m_bufferViewHandles[firstElement] : DE_NULL                 // const VkBufferView*                          pTexelBufferView
+       };
+
+       return descriptorWrite;
+}
+
+void BufferDescriptor::invalidate (Context& context)
+{
+       const DeviceInterface&  vk              = context.getDeviceInterface();
+    const VkDevice                     device  = context.getDevice();
+
+       invalidateMappedMemoryRange(vk, device, m_buffer->getAllocation().getMemory(), m_buffer->getAllocation().getOffset(), m_bufferSize);
+}
+
+// Returns the buffer data as a vector
+vector<deUint32> BufferDescriptor::getData (void)
+{
+       vector<deUint32>        data;
+       deInt32*                        hostPtr = (deInt32*)m_buffer->getAllocation().getHostPtr();
+
+       for (deUint32 i = 0; i < m_arraySize; i++)
+               data.push_back(hostPtr[i]);
+
+       return data;
+}
+
+UniformBufferDescriptor::UniformBufferDescriptor (deUint32     arraySize,
+                                                                                                 deUint32      writeStart,
+                                                                                                 deUint32      elementsToWrite,
+                                                                                                 deUint32      numDynamicAreas)
+: BufferDescriptor(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, arraySize, writeStart, elementsToWrite, 1u)
+{
+       DE_UNREF(numDynamicAreas);
+}
+
+UniformBufferDescriptor::~UniformBufferDescriptor (void)
+{
+}
+
+string UniformBufferDescriptor::getShaderDeclaration (void) const
+{
+       return string(
+               ") uniform UniformBuffer" + de::toString(m_id) + "\n"
+               "{\n"
+               "       int data;\n"
+               "} uniformBuffer" + de::toString(m_id) + getArrayString(m_arraySize) +  ";\n");
+}
+
+string UniformBufferDescriptor::getShaderVerifyCode (void) const
+{
+       string ret;
+
+       for (deUint32 i = 0; i < m_arraySize; i++)
+       {
+               if (m_data[i].written || m_data[i].copiedInto)
+                       ret += string("if (uniformBuffer") + de::toString(m_id) + getArrayString(i) + ".data != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
+       }
+
+       return ret;
+}
+
+DynamicUniformBufferDescriptor::DynamicUniformBufferDescriptor (deUint32       arraySize,
+                                                                                                                               deUint32        writeStart,
+                                                                                                                               deUint32        elementsToWrite,
+                                                                                                                               deUint32        numDynamicAreas)
+: BufferDescriptor(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, arraySize, writeStart, elementsToWrite, numDynamicAreas)
+{
+}
+
+DynamicUniformBufferDescriptor::~DynamicUniformBufferDescriptor (void)
+{
+}
+
+string DynamicUniformBufferDescriptor::getShaderDeclaration (void) const
+{
+       return string(
+               ") uniform UniformBuffer" + de::toString(m_id) + "\n"
+               "{\n"
+               "       int data;\n"
+               "} dynamicUniformBuffer" + de::toString(m_id) + getArrayString(m_arraySize) +  ";\n");
+}
+
+string DynamicUniformBufferDescriptor::getShaderVerifyCode (void) const
+{
+       string ret;
+
+       for (deUint32 arrayIdx = 0; arrayIdx < m_arraySize; arrayIdx++)
+       {
+               if (m_data[arrayIdx].written || m_data[arrayIdx].copiedInto)
+                       ret += string("if (dynamicUniformBuffer") + de::toString(m_id) + getArrayString(arrayIdx) + ".data != " + de::toString(m_data[arrayIdx].data[m_dynamicAreas[arrayIdx]]) + ") result = 0;\n";
+       }
+
+       return ret;
+}
+
+StorageBufferDescriptor::StorageBufferDescriptor (deUint32     arraySize,
+                                                                                                 deUint32      writeStart,
+                                                                                                 deUint32      elementsToWrite,
+                                                                                                 deUint32      numDynamicAreas)
+: BufferDescriptor(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, arraySize, writeStart, elementsToWrite, 1u)
+{
+       DE_UNREF(numDynamicAreas);
+}
+
+StorageBufferDescriptor::~StorageBufferDescriptor (void)
+{
+}
+
+string StorageBufferDescriptor::getShaderDeclaration (void) const
+{
+       return string(
+               ") buffer StorageBuffer" + de::toString(m_id) + "\n"
+               "{\n"
+               "       int data;\n"
+               "} storageBuffer" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
+}
+
+string StorageBufferDescriptor::getShaderVerifyCode (void) const
+{
+       string ret;
+
+       for (deUint32 i = 0; i < m_arraySize; i++)
+       {
+               if (m_data[i].written || m_data[i].copiedInto)
+                       ret += string("if (storageBuffer") + de::toString(m_id) + getArrayString(i) + ".data != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
+       }
+
+       return ret;
+}
+
+DynamicStorageBufferDescriptor::DynamicStorageBufferDescriptor (deUint32       arraySize,
+                                                                                                                               deUint32        writeStart,
+                                                                                                                               deUint32        elementsToWrite,
+                                                                                                                               deUint32        numDynamicAreas)
+: BufferDescriptor(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, arraySize, writeStart, elementsToWrite, numDynamicAreas)
+{
+}
+
+DynamicStorageBufferDescriptor::~DynamicStorageBufferDescriptor (void)
+{
+}
+
+string DynamicStorageBufferDescriptor::getShaderDeclaration (void) const
+{
+       return string(
+               ") buffer StorageBuffer" + de::toString(m_id) + "\n"
+               "{\n"
+               "       int data;\n"
+               "} dynamicStorageBuffer" + de::toString(m_id) + getArrayString(m_arraySize) +  ";\n");
+}
+
+string DynamicStorageBufferDescriptor::getShaderVerifyCode (void) const
+{
+       string ret;
+
+       for (deUint32 arrayIdx = 0; arrayIdx < m_arraySize; arrayIdx++)
+       {
+               if (m_data[arrayIdx].written || m_data[arrayIdx].copiedInto)
+                       ret += string("if (dynamicStorageBuffer") + de::toString(m_id) + getArrayString(arrayIdx) + ".data != " + de::toString(m_data[arrayIdx].data[m_dynamicAreas[arrayIdx]]) + ") result = 0;\n";
+       }
+
+       return ret;
+}
+
+UniformTexelBufferDescriptor::UniformTexelBufferDescriptor (deUint32   arraySize,
+                                                                                                                       deUint32        writeStart,
+                                                                                                                       deUint32        elementsToWrite,
+                                                                                                                       deUint32        numDynamicAreas)
+: BufferDescriptor(VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, arraySize, writeStart, elementsToWrite, 1u)
+{
+       DE_UNREF(numDynamicAreas);
+}
+
+UniformTexelBufferDescriptor::~UniformTexelBufferDescriptor (void)
+{
+}
+
+string UniformTexelBufferDescriptor::getShaderDeclaration (void) const
+{
+       return string(") uniform textureBuffer uniformTexelBuffer" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
+}
+
+string UniformTexelBufferDescriptor::getShaderVerifyCode (void) const
+{
+       string ret;
+
+       for (deUint32 i = 0; i < m_arraySize; i++)
+       {
+               if (m_data[i].written || m_data[i].copiedInto)
+                       ret += string("if (texelFetch(uniformTexelBuffer") + de::toString(m_id) + getArrayString(i) + ", 0).x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
+       }
+
+       return ret;
+}
+
+StorageTexelBufferDescriptor::StorageTexelBufferDescriptor (deUint32   arraySize,
+                                                                                                                       deUint32        writeStart,
+                                                                                                                       deUint32        elementsToWrite,
+                                                                                                                       deUint32        numDynamicAreas)
+: BufferDescriptor(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, arraySize, writeStart, elementsToWrite, 1u)
+{
+       DE_UNREF(numDynamicAreas);
+}
+
+StorageTexelBufferDescriptor::~StorageTexelBufferDescriptor (void)
+{
+}
+
+string StorageTexelBufferDescriptor::getShaderDeclaration (void) const
+{
+       return string(", r32f) uniform imageBuffer storageTexelBuffer" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
+}
+
+string StorageTexelBufferDescriptor::getShaderVerifyCode (void) const
+{
+       string ret;
+
+       for (deUint32 i = 0; i < m_arraySize; i++)
+       {
+               if (m_data[i].written || m_data[i].copiedInto)
+                       ret += string("if (imageLoad(storageTexelBuffer") + de::toString(m_id) + getArrayString(i) + ", 0).x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
+       }
+
+       return ret;
+}
+
+ImageDescriptor::ImageDescriptor (VkDescriptorType     type,
+                                                                 deUint32                      arraySize,
+                                                                 deUint32                      writeStart,
+                                                                 deUint32                      elementsToWrite,
+                                                                 deUint32                      numDynamicAreas)
+: Descriptor(type, arraySize, writeStart, elementsToWrite, 1u)
+{
+       DE_UNREF(numDynamicAreas);
+}
+
+ImageDescriptor::~ImageDescriptor (void)
+{
+}
+
+void ImageDescriptor::init (Context&           context,
+                                                       PipelineType    pipelineType)
+{
+       const DeviceInterface&                  vk                                      = context.getDeviceInterface();
+    const VkDevice                                     device                          = context.getDevice();
+    Allocator&                                         allocator                       = context.getDefaultAllocator();
+       const VkQueue                                   queue                           = context.getUniversalQueue();
+       deUint32                                                queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
+       const VkFormat                                  format                          = VK_FORMAT_R32_SFLOAT;
+       const VkComponentMapping                componentMapping        = makeComponentMappingRGBA();
+
+       const VkImageSubresourceRange   subresourceRange        =
+       {
+               VK_IMAGE_ASPECT_COLOR_BIT,      // VkImageAspectFlags   aspectMask
+               0u,                                                     // deUint32                             baseMipLevel
+               1u,                                                     // deUint32                             levelCount
+               0u,                                                     // deUint32                             baseArrayLayer
+               1u,                                                     // deUint32                             layerCount
+       };
+
+       // Create sampler
+       {
+               const tcu::Sampler                      sampler                 = tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST);
+               const tcu::TextureFormat        texFormat               = mapVkFormat(format);
+               const VkSamplerCreateInfo       samplerParams   = mapSampler(sampler, texFormat);
+
+               m_sampler = createSampler(vk, device, &samplerParams);
+       }
+
+       // Create images
+       for (deUint32 imageIdx = 0; imageIdx < m_arraySize; imageIdx++)
+       {
+               const VkImageCreateInfo imageCreateInfo =
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                            // VkStructureType                      stype
+                       DE_NULL,                                                                                                        // const void*                          pNext
+                       0u,                                                                                                                     // VkImageCreateFlags           flags
+                       VK_IMAGE_TYPE_2D,                                                                                       // VkImageType                          imageType
+                       format,                                                                                                         // VkFormat                                     format
+                       { (deUint32)renderSize.x(), (deUint32)renderSize.y(), 1 },      // VkExtent3D                           extent
+                       1u,                                                                                                                     // deUint32                                     mipLevels
+                       1u,                                                                                                                     // deUint32                                     arrayLayers
+                       VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits        samples
+                       VK_IMAGE_TILING_OPTIMAL,                                                                        // VkImageTiling                        tiling
+                       getImageUsageFlags(),                                                                           // VkImageUsageFlags            usage
+                       VK_SHARING_MODE_EXCLUSIVE,                                                                      // VkSharingMode                        sharingMode
+                       1u,                                                                                                                     // deUint32                                     queueFamilyIndexCount
+                       &queueFamilyIndex,                                                                                      // const deUint32*                      pQueueFamilyIndices
+                       VK_IMAGE_LAYOUT_UNDEFINED,                                                                      // VkImageLayout                        initialLayout
+               };
+
+               m_images.push_back(ImageWithMemorySp(new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any)));
+       }
+
+       // Create image views
+       for (deUint32 imageIdx = 0; imageIdx < m_arraySize; imageIdx++)
+       {
+               const VkImageViewCreateInfo imageViewCreateInfo =
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType                      sType
+                       DE_NULL,                                                                        // const void*                          pNext
+                       0u,                                                                                     // VkImageViewCreateFlags       flags
+                       **m_images[imageIdx],                                           // VkImage                                      image
+                       VK_IMAGE_VIEW_TYPE_2D,                                          // VkImageViewType                      viewType
+                       format,                                                                         // VkFormat                                     format
+                       componentMapping,                                                       // VkComponentMapping           components
+                       subresourceRange                                                        // VkImageSubresourceRange      subresourceRange
+               };
+
+               m_imageViews.push_back(VkImageViewSp(new Unique<VkImageView>(createImageView(vk, device, &imageViewCreateInfo))));
+       }
+
+       // Create descriptor image infos
+       {
+               for (deUint32 i = 0; i < m_arraySize; i++)
+               {
+                       const VkDescriptorImageInfo imageInfo =
+                       {
+                               *m_sampler,                     // VkSampler            sampler
+                               **m_imageViews[i],      // VkImageView          imageView
+                               getImageLayout()        // VkImageLayout        imageLayout
+                       };
+
+                       m_descriptorImageInfos.push_back(imageInfo);
+               }
+       }
+
+       // Clear images to reference value
+       for (deUint32 imageIdx = 0; imageIdx < m_arraySize; imageIdx++)
+       {
+               const Unique<VkCommandPool>             cmdPool                         (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex));
+               const Unique<VkCommandBuffer>   cmdBuffer                       (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+
+               const float                                             clearValue                      = (float)(m_id + imageIdx);
+               const VkClearValue                              clearColor                      = makeClearValueColorF32(clearValue, clearValue, clearValue, clearValue);
+
+               const VkImageMemoryBarrier              preImageBarrier         =
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType
+                       DE_NULL,                                                                        // const void*                          pNext
+                       0u,                                                                                     // VkAccessFlags                        srcAccessMask
+                       VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags                        dstAccessMask
+                       VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                        oldLayout
+                       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,           // VkImageLayout                        newLayout
+                       queueFamilyIndex,                                                       // deUint32                                     srcQueueFamilyIndex
+                       queueFamilyIndex,                                                       // deUint32                                     dstQueueFamilyIndex
+                       **m_images[imageIdx],                                           // VkImage                                      image
+                       subresourceRange                                                        // VkImageSubresourceRange      subresourceRange
+               };
+
+               const VkImageMemoryBarrier              postImageBarrier        =
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,         // VkStructureType                      sType
+                       DE_NULL,                                                                        // const void*                          pNext
+                       VK_ACCESS_TRANSFER_WRITE_BIT,                           // VkAccessFlags                        srcAccessMask
+                       getAccessFlags(),                                                       // VkAccessFlags                        dstAccessMask
+                       VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,           // VkImageLayout                        oldLayout
+                       getImageLayout(),                                                       // VkImageLayout                        newLayout
+                       queueFamilyIndex,                                                       // deUint32                                     srcQueueFamilyIndex
+                       queueFamilyIndex,                                                       // deUint32                                     dstQueueFamilyIndex
+                       **m_images[imageIdx],                                           // VkImage                                      image
+                       subresourceRange                                                        // VkImageSubresourceRange      subresourceRange
+               };
+
+               beginCommandBuffer(vk, *cmdBuffer);
+               vk.cmdPipelineBarrier(*cmdBuffer,
+                                                         VK_PIPELINE_STAGE_HOST_BIT,
+                                                         VK_PIPELINE_STAGE_TRANSFER_BIT,
+                                                         (VkDependencyFlags)0u,
+                                                         0u, (const VkMemoryBarrier*)DE_NULL,
+                                                         0u, (const VkBufferMemoryBarrier*)DE_NULL,
+                                                         1u, &preImageBarrier);
+               vk.cmdClearColorImage(*cmdBuffer, **m_images[imageIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor.color, 1, &subresourceRange);
+               vk.cmdPipelineBarrier(*cmdBuffer,
+                                                         VK_PIPELINE_STAGE_TRANSFER_BIT,
+                                                         pipelineType == PIPELINE_TYPE_COMPUTE ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT : VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+                                                         (VkDependencyFlags)0u,
+                                                         0u, (const VkMemoryBarrier*)DE_NULL,
+                                                         0u, (const VkBufferMemoryBarrier*)DE_NULL,
+                                                         1u, &postImageBarrier);
+               endCommandBuffer(vk, *cmdBuffer);
+               submitCommandsAndWait(vk, device, queue, *cmdBuffer);
+       }
+}
+
+VkWriteDescriptorSet ImageDescriptor::getDescriptorWrite (void)
+{
+       const deUint32                          firstElement    = getFirstWrittenElement();
+
+       // Set and binding will be overwritten later
+       const VkWriteDescriptorSet      descriptorWrite =
+       {
+               VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType                                      sType
+               DE_NULL,                                                                // const void*                                          pNext
+               (VkDescriptorSet)0u,                                    // VkDescriptorSet                                      dstSet
+               0u,                                                                             // deUint32                                                     dstBinding
+               firstElement,                                                   // deUint32                                                     dstArrayElement
+               getNumWrittenElements(),                                // deUint32                                                     descriptorCount
+               getType(),                                                              // VkDescriptorType                                     descriptorType
+               &m_descriptorImageInfos[firstElement],  // const VkDescriptorImageInfo          pImageInfo
+               DE_NULL,                                                                // const VkDescriptorBufferInfo*        pBufferInfo
+               DE_NULL                                                                 // const VkBufferView*                          pTexelBufferView
+       };
+
+       return descriptorWrite;
+}
+
+InputAttachmentDescriptor::InputAttachmentDescriptor (deUint32 arraySize,
+                                                                                                         deUint32      writeStart,
+                                                                                                         deUint32      elementsToWrite,
+                                                                                                         deUint32      numDynamicAreas)
+: ImageDescriptor(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, arraySize, writeStart, elementsToWrite, 1u)
+, m_originalAttachmentIndex(s_nextAttachmentIndex)
+{
+       DE_UNREF(numDynamicAreas);
+
+       for (deUint32 i = 0; i < m_arraySize; i++)
+               m_attachmentIndices.push_back(s_nextAttachmentIndex++);
+}
+
+InputAttachmentDescriptor::~InputAttachmentDescriptor (void)
+{
+}
+
+string InputAttachmentDescriptor::getShaderDeclaration (void) const
+{
+       return string(", input_attachment_index=" + de::toString(m_originalAttachmentIndex) + ") uniform subpassInput inputAttachment" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
+}
+
+string InputAttachmentDescriptor::getShaderVerifyCode (void) const
+{
+       string ret;
+
+       for (deUint32 i = 0; i < m_arraySize; i++)
+       {
+               if (m_data[i].written || m_data[i].copiedInto)
+                       ret += string("if (subpassLoad(inputAttachment") + de::toString(m_id) + getArrayString(i) + ").x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
+       }
+
+       return ret;
+}
+
+void InputAttachmentDescriptor::copyValue (const Descriptor&   src,
+                                                                                  deUint32                             srcElement,
+                                                                                  deUint32                             dstElement,
+                                                                                  deUint32                             numElements)
+{
+       Descriptor::copyValue(src, srcElement, dstElement, numElements);
+
+       for (deUint32 elementIdx = 0; elementIdx < numElements; elementIdx++)
+       {
+               m_attachmentIndices[elementIdx + dstElement] = reinterpret_cast<const InputAttachmentDescriptor&>(src).m_attachmentIndices[elementIdx + srcElement];
+       }
+}
+
+vector<VkAttachmentReference> InputAttachmentDescriptor::getAttachmentReferences (void) const
+{
+       vector<VkAttachmentReference> references;
+       for (deUint32 i = 0; i < m_arraySize; i++)
+       {
+               const VkAttachmentReference attachmentReference =
+               {
+                       // The first attachment is the color buffer, thus +1
+                       m_attachmentIndices[i] + 1,     // deUint32                     attachment
+                       getImageLayout()                        // VkImageLayout        layout
+               };
+
+               references.push_back(attachmentReference);
+       }
+
+       return references;
+}
+
+CombinedImageSamplerDescriptor::CombinedImageSamplerDescriptor (deUint32       arraySize,
+                                                                                                                               deUint32        writeStart,
+                                                                                                                               deUint32        elementsToWrite,
+                                                                                                                               deUint32        numDynamicAreas)
+: ImageDescriptor(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, arraySize, writeStart, elementsToWrite, 1u)
+{
+       DE_UNREF(numDynamicAreas);
+}
+
+CombinedImageSamplerDescriptor::~CombinedImageSamplerDescriptor (void)
+{
+}
+
+string CombinedImageSamplerDescriptor::getShaderDeclaration (void) const
+{
+       return string(") uniform sampler2D texSampler" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
+}
+
+string CombinedImageSamplerDescriptor::getShaderVerifyCode (void) const
+{
+       string ret;
+
+       for (deUint32 i = 0; i < m_arraySize; i++)
+       {
+               if (m_data[i].written || m_data[i].copiedInto)
+                       ret += string("if (texture(texSampler") + de::toString(m_id) + getArrayString(i) + ", vec2(0)).x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
+       }
+
+       return ret;
+}
+
+SampledImageDescriptor::SampledImageDescriptor (deUint32       arraySize,
+                                                                                               deUint32        writeStart,
+                                                                                               deUint32        elementsToWrite,
+                                                                                               deUint32        numDynamicAreas)
+: ImageDescriptor(VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, arraySize, writeStart, elementsToWrite, 1u)
+{
+       DE_UNREF(numDynamicAreas);
+}
+
+SampledImageDescriptor::~SampledImageDescriptor (void)
+{
+}
+
+string SampledImageDescriptor::getShaderDeclaration (void) const
+{
+       return string(") uniform texture2D sampledImage" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
+}
+
+string SampledImageDescriptor::getShaderVerifyCode (void) const
+{
+       string ret;
+
+       for (deUint32 i = 0; i < m_arraySize; i++)
+       {
+               if ((m_data[i].written || m_data[i].copiedInto) && m_samplers.size() > i)
+               {
+                       ret += string("if (texture(sampler2D(sampledImage") + de::toString(m_id) + getArrayString(i) + ", sampler" + de::toString(m_samplers[i]->getId()) + "), vec2(0)).x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
+               }
+       }
+
+       return ret;
+}
+
+StorageImageDescriptor::StorageImageDescriptor (deUint32       arraySize,
+                                                                                               deUint32        writeStart,
+                                                                                               deUint32        elementsToWrite,
+                                                                                               deUint32        numDynamicAreas)
+: ImageDescriptor(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, arraySize, writeStart, elementsToWrite, 1u)
+{
+       DE_UNREF(numDynamicAreas);
+}
+
+StorageImageDescriptor::~StorageImageDescriptor (void)
+{
+}
+
+string StorageImageDescriptor::getShaderDeclaration (void) const
+{
+       return string(", r32f) readonly uniform image2D image" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
+}
+
+string StorageImageDescriptor::getShaderVerifyCode (void) const
+{
+       string ret;
+
+       for (deUint32 i = 0; i < m_arraySize; i++)
+       {
+               if (m_data[i].written || m_data[i].copiedInto)
+                       ret += string("if (imageLoad(image") + de::toString(m_id) + getArrayString(i) + ", ivec2(0)).x != " + de::toString(m_data[i].data[0]) + ") result = 0;\n";
+       }
+
+       return ret;
+}
+
+SamplerDescriptor::SamplerDescriptor (deUint32 arraySize,
+                                                                         deUint32      writeStart,
+                                                                         deUint32      elementsToWrite,
+                                                                         deUint32      numDynamicAreas)
+: Descriptor(VK_DESCRIPTOR_TYPE_SAMPLER, arraySize, writeStart, elementsToWrite, 1u)
+{
+       DE_UNREF(numDynamicAreas);
+}
+
+SamplerDescriptor::~SamplerDescriptor (void)
+{
+}
+
+void SamplerDescriptor::init (Context&         context,
+                                                         PipelineType  pipelineType)
+{
+       DE_UNREF(pipelineType);
+
+       const DeviceInterface&  vk              = context.getDeviceInterface();
+    const VkDevice                     device  = context.getDevice();
+       const VkFormat                  format  = VK_FORMAT_R32_SFLOAT;
+
+       // Create samplers
+       for (deUint32 i = 0; i < m_arraySize; i++)
+       {
+               const float                                     borderValue             = (float)((m_id + i) % 2);
+               const tcu::Sampler                      sampler                 = tcu::Sampler(tcu::Sampler::CLAMP_TO_BORDER, tcu::Sampler::CLAMP_TO_BORDER, tcu::Sampler::CLAMP_TO_BORDER, tcu::Sampler::NEAREST, tcu::Sampler::NEAREST, 0.0f, true, tcu::Sampler::COMPAREMODE_NONE, 0, Vec4(borderValue));
+               const tcu::TextureFormat        texFormat               = mapVkFormat(format);
+               const VkSamplerCreateInfo       samplerParams   = mapSampler(sampler, texFormat);
+
+               m_samplers.push_back(VkSamplerSp(new Unique<VkSampler>(createSampler(vk, device, &samplerParams))));
+       }
+
+       // Create descriptor image infos
+       for (deUint32 i = 0; i < m_arraySize; i++)
+       {
+               const VkDescriptorImageInfo imageInfo =
+               {
+                       **m_samplers[i],                        // VkSampler            sampler
+                       DE_NULL,                                        // VkImageView          imageView
+                       VK_IMAGE_LAYOUT_UNDEFINED       // VkImageLayout        imageLayout
+               };
+
+               m_descriptorImageInfos.push_back(imageInfo);
+       }
+}
+
+VkWriteDescriptorSet SamplerDescriptor::getDescriptorWrite (void)
+{
+       const deUint32 firstElement = getFirstWrittenElement();
+
+       // Set and binding will be overwritten later
+       const VkWriteDescriptorSet      descriptorWrite =
+       {
+               VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType                                      sType
+               DE_NULL,                                                                // const void*                                          pNext
+               (VkDescriptorSet)0u,                                    // VkDescriptorSet                                      dstSet
+               0u,                                                                             // deUint32                                                     dstBinding
+               firstElement,                                                   // deUint32                                                     dstArrayElement
+               getNumWrittenElements(),                                // deUint32                                                     descriptorCount
+               getType(),                                                              // VkDescriptorType                                     descriptorType
+               &m_descriptorImageInfos[firstElement],  // const VkDescriptorImageInfo          pImageInfo
+               DE_NULL,                                                                // const VkDescriptorBufferInfo*        pBufferInfo
+               DE_NULL                                                                 // const VkBufferView*                          pTexelBufferView
+       };
+
+       return descriptorWrite;
+}
+
+string SamplerDescriptor::getShaderDeclaration (void) const
+{
+       return string(") uniform sampler sampler" + de::toString(m_id) + getArrayString(m_arraySize) + ";\n");
+}
+
+string SamplerDescriptor::getShaderVerifyCode (void) const
+{
+       string ret;
+
+       for (deUint32 i = 0; i < m_arraySize; i++)
+       {
+               if ((m_data[i].written || m_data[i].copiedInto) && m_images.size() > i)
+               {
+                       // Sample from (-1, -1) to get border color.
+                       ret += string("if (texture(sampler2D(sampledImage") + de::toString(m_images[i]->getId()) + ", sampler" + de::toString(m_id) + getArrayString(i) + "), vec2(-1)).x != " + de::toString(m_data[i].data[0] % 2) + ") result = 0;\n";
+               }
+       }
+
+       return ret;
+}
+
+DescriptorSet::DescriptorSet (void)
+{
+}
+
+DescriptorSet::~DescriptorSet (void)
+{
+}
+
+void DescriptorSet::addBinding (DescriptorSp descriptor)
+{
+       m_bindings.push_back(descriptor);
+}
+
+DescriptorCommands::DescriptorCommands (PipelineType pipelineType)
+: m_pipelineType(pipelineType)
+{
+       // Reset counters
+       Descriptor::s_nextId = 0xabc;
+       InputAttachmentDescriptor::s_nextAttachmentIndex = 0;
+}
+
+DescriptorCommands::~DescriptorCommands (void)
+{
+}
+
+void DescriptorCommands::addDescriptor (DescriptorSp   descriptor,
+                                                                               deUint32                descriptorSet)
+{
+       const VkDescriptorType type = descriptor->getType();
+
+       // Create descriptor set objects until one with the given index exists
+       while (m_descriptorSets.size() <= descriptorSet)
+               m_descriptorSets.push_back(DescriptorSetSp(new DescriptorSet()));
+
+       m_descriptorSets[descriptorSet]->addBinding(descriptor);
+
+       // Keep track of how many descriptors of each type is needed
+       if (m_descriptorCounts.find(type) != m_descriptorCounts.end())
+               m_descriptorCounts[type] += descriptor->getArraySize();
+       else
+               m_descriptorCounts[type] = descriptor->getArraySize();
+
+       // Keep descriptors also in a flat list for easier iteration
+       m_descriptors.push_back(descriptor);
+}
+
+void DescriptorCommands::copyDescriptor (deUint32      srcSet,
+                                                                                deUint32       srcBinding,
+                                                                                deUint32       srcArrayElement,
+                                                                                deUint32       dstSet,
+                                                                                deUint32       dstBinding,
+                                                                                deUint32       dstArrayElement,
+                                                                                deUint32       descriptorCount)
+{
+       const DescriptorCopy descriptorCopy = { srcSet, srcBinding, srcArrayElement, dstSet, dstBinding, dstArrayElement, descriptorCount };
+       m_descriptorCopies.push_back(descriptorCopy);
+       m_descriptorSets[descriptorCopy.dstSet]->getBindings()[descriptorCopy.dstBinding]->copyValue(*m_descriptorSets[descriptorCopy.srcSet]->getBindings()[descriptorCopy.srcBinding], srcArrayElement, dstArrayElement, descriptorCount);
+}
+
+// Generates shader source code for declarations of all descriptors
+string DescriptorCommands::getShaderDeclarations (void) const
+{
+       string ret;
+
+       for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
+       {
+               const vector<DescriptorSp> bindings = m_descriptorSets[descriptorSetIdx]->getBindings();
+
+               for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
+               {
+                       ret += "layout (set=" + de::toString(descriptorSetIdx) + ", binding=" + de::toString(bindingIdx) + bindings[bindingIdx]->getShaderDeclaration();
+               }
+       }
+
+       return ret;
+}
+
+// Generates shader source code for verification of all descriptor data
+string DescriptorCommands::getDescriptorVerifications (void) const
+{
+       string ret;
+
+       for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
+       {
+               const vector<DescriptorSp> bindings = m_descriptorSets[descriptorSetIdx]->getBindings();
+
+               for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
+               {
+                       if (m_pipelineType == PIPELINE_TYPE_COMPUTE && descriptorSetIdx == 0 && bindingIdx == bindings.size() - 1) continue; // Skip the result buffer which is always the last descriptor of set 0
+                       ret += bindings[bindingIdx]->getShaderVerifyCode();
+               }
+       }
+
+       return ret;
+}
+
+void DescriptorCommands::addResultBuffer (void)
+{
+       // Add result buffer if using compute pipeline
+       if (m_pipelineType == PIPELINE_TYPE_COMPUTE)
+       {
+               m_resultBuffer = DescriptorSp(new StorageBufferDescriptor());
+               addDescriptor(m_resultBuffer, 0u);
+       }
+}
+
+// Sets the list of dynamic areas selected for each dynamic descriptor when running the verification shader
+void DescriptorCommands::setDynamicAreas (vector<deUint32> areas)
+{
+       m_dynamicAreas = areas;
+       deUint32 areaIdx = 0;
+
+       for (vector<DescriptorSp>::iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++)
+       {
+               if ((*desc)->isDynamic())
+               {
+                       vector<deUint32> dynamicAreas;
+
+                       for (deUint32 elementIdx = 0; elementIdx < (*desc)->getArraySize(); elementIdx++)
+                               dynamicAreas.push_back(areas[areaIdx++]);
+
+                       (*desc)->setDynamicAreas(dynamicAreas);
+               }
+       }
+}
+
+bool DescriptorCommands::hasDynamicAreas (void) const
+{
+       for (vector<DescriptorSp>::const_iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++)
+               if ((*desc)->isDynamic())
+                       return true;
+
+       return false;
+}
+
+tcu::TestStatus DescriptorCommands::run (Context& context)
+{
+       const DeviceInterface&                                  vk                                      = context.getDeviceInterface();
+    const VkDevice                                                     device                          = context.getDevice();
+       const VkQueue                                                   queue                           = context.getUniversalQueue();
+       const VkPhysicalDeviceLimits                    limits                          = getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice()).limits;
+       const deUint32                                                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
+    Allocator&                                                         allocator                       = context.getDefaultAllocator();
+       tcu::TestLog&                                                   log                                     = context.getTestContext().getLog();
+       const Unique<VkCommandPool>                             commandPool                     (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex));
+       const Unique<VkCommandBuffer>                   commandBuffer           (allocateCommandBuffer(vk, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
+       const VkShaderStageFlags                                shaderStage                     = m_pipelineType == PIPELINE_TYPE_COMPUTE ? VK_SHADER_STAGE_COMPUTE_BIT : VK_SHADER_STAGE_FRAGMENT_BIT;
+       const VkFormat                                                  resultFormat            = VK_FORMAT_R8G8B8A8_UNORM;
+       de::MovePtr<ImageWithMemory>                    resultImage;
+       de::MovePtr<BufferWithMemory>                   resultImageBuffer;
+       Move<VkImageView>                                               resultImageView;
+       Move<VkRenderPass>                                              renderPass;
+       Move<VkFramebuffer>                                             framebuffer;
+       Move<VkDescriptorPool>                                  descriptorPool;
+       vector<VkDescriptorSetLayoutSp>                 descriptorSetLayouts;
+       vector<VkDescriptorSet>                                 descriptorSets;
+       Move<VkPipelineLayout>                                  pipelineLayout;
+       Move<VkPipeline>                                                pipeline;
+       vector<VkAttachmentReference>                   inputAttachments;
+       vector<VkAttachmentDescription>                 attachmentDescriptions;
+       vector<VkImageView>                                             imageViews;
+
+       // Check physical device limits of per stage and per desriptor set descriptor count
+       {
+               deUint32        numPerStageSamplers                     = 0;
+               deUint32        numPerStageUniformBuffers       = 0;
+               deUint32        numPerStageStorageBuffers       = 0;
+               deUint32        numPerStageSampledImages        = 0;
+               deUint32        numPerStageStorageImages        = 0;
+               deUint32        numPerStageInputAttachments     = 0;
+               deUint32        numPerStageTotalResources       = 0;
+
+               for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
+               {
+                       deUint32                                        numSamplers                                     = 0;
+                       deUint32                                        numUniformBuffers                       = 0;
+                       deUint32                                        numUniformBuffersDynamic        = 0;
+                       deUint32                                        numStorageBuffers                       = 0;
+                       deUint32                                        numStorageBuffersDynamic        = 0;
+                       deUint32                                        numSampledImages                        = 0;
+                       deUint32                                        numStorageImages                        = 0;
+                       deUint32                                        numInputAttachments                     = 0;
+                       deUint32                                        numTotalResources                       = m_pipelineType == PIPELINE_TYPE_GRAPHICS ? 1u : 0u; // Color buffer counts as a resource.
+
+                       const vector<DescriptorSp>&     bindings                                        = m_descriptorSets[descriptorSetIdx]->getBindings();
+
+                       for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
+                       {
+                               const deUint32 arraySize = bindings[bindingIdx]->getArraySize();
+
+                               numTotalResources += arraySize;
+
+                               switch (bindings[bindingIdx]->getType())
+                               {
+                                       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+                                               numUniformBuffers += arraySize;
+                                               break;
+
+                                       case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+                                               numUniformBuffers += arraySize;
+                                               numUniformBuffersDynamic += arraySize;
+                                               break;
+
+                                       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+                                               numStorageBuffers += arraySize;
+                                               break;
+
+                                       case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+                                               numStorageBuffers += arraySize;
+                                               numStorageBuffersDynamic += arraySize;
+                                               break;
+
+                                       case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
+                                               numSamplers += arraySize;
+                                               numSampledImages += arraySize;
+                                               break;
+
+                                       case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
+                                       case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+                                               numStorageImages += arraySize;
+                                               break;
+
+                                       case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+                                               numInputAttachments += arraySize;
+                                               break;
+
+                                       case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+                                       case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+                                               numSampledImages += arraySize;
+                                               break;
+
+                                       case VK_DESCRIPTOR_TYPE_SAMPLER:
+                                               numSamplers += arraySize;
+                                               break;
+
+                                       default:
+                                               DE_FATAL("Unexpected descriptor type");
+                                               break;
+                               }
+                       }
+
+                       if (numSamplers > limits.maxDescriptorSetSamplers)
+                               TCU_THROW(NotSupportedError, "Maximum per descriptor set sampler limit exceeded.");
+
+                       if (numUniformBuffers > limits.maxDescriptorSetUniformBuffers)
+                               TCU_THROW(NotSupportedError, "Maximum per descriptor set uniform buffer limit exceeded.");
+
+                       if (numUniformBuffersDynamic > limits.maxDescriptorSetUniformBuffersDynamic)
+                               TCU_THROW(NotSupportedError, "Maximum per descriptor set uniform buffer dynamic limit exceeded.");
+
+                       if (numStorageBuffers > limits.maxDescriptorSetStorageBuffers)
+                               TCU_THROW(NotSupportedError, "Maximum per descriptor set storage buffer limit exceeded.");
+
+                       if (numStorageBuffersDynamic > limits.maxDescriptorSetStorageBuffersDynamic)
+                               TCU_THROW(NotSupportedError, "Maximum per descriptor set storage buffer dynamic limit exceeded.");
+
+                       if (numSampledImages > limits.maxDescriptorSetSampledImages)
+                               TCU_THROW(NotSupportedError, "Maximum per descriptor set sampled image limit exceeded.");
+
+                       if (numStorageImages > limits.maxDescriptorSetStorageImages)
+                               TCU_THROW(NotSupportedError, "Maximum per descriptor set storage image limit exceeded.");
+
+                       if (numInputAttachments > limits.maxDescriptorSetInputAttachments)
+                               TCU_THROW(NotSupportedError, "Maximum per descriptor set input attachment limit exceeded.");
+
+                       numPerStageSamplers                     += numSamplers;
+                       numPerStageUniformBuffers       += numUniformBuffers;
+                       numPerStageStorageBuffers       += numStorageBuffers;
+                       numPerStageSampledImages        += numSampledImages;
+                       numPerStageStorageImages        += numStorageImages;
+                       numPerStageInputAttachments     += numInputAttachments;
+                       numPerStageTotalResources       += numTotalResources;
+               }
+
+               if (numPerStageTotalResources > limits.maxPerStageResources)
+                       TCU_THROW(NotSupportedError, "Maximum per stage total resource limit exceeded.");
+
+               if (numPerStageSamplers > limits.maxPerStageDescriptorSamplers)
+                       TCU_THROW(NotSupportedError, "Maximum per stage sampler limit exceeded.");
+
+               if (numPerStageUniformBuffers > limits.maxPerStageDescriptorUniformBuffers)
+                       TCU_THROW(NotSupportedError, "Maximum per stage uniform buffer limit exceeded.");
+
+               if (numPerStageStorageBuffers > limits.maxPerStageDescriptorStorageBuffers)
+                       TCU_THROW(NotSupportedError, "Maximum per stage storage buffer limit exceeded.");
+
+               if (numPerStageSampledImages > limits.maxPerStageDescriptorSampledImages)
+                       TCU_THROW(NotSupportedError, "Maximum per stage sampled image limit exceeded.");
+
+               if (numPerStageStorageImages > limits.maxPerStageDescriptorStorageImages)
+                       TCU_THROW(NotSupportedError, "Maximum per stage storage image limit exceeded.");
+
+               if (numPerStageInputAttachments > limits.maxPerStageDescriptorInputAttachments)
+                       TCU_THROW(NotSupportedError, "Maximum per stage input attachment limit exceeded.");
+       }
+
+       // Initialize all descriptors
+       for (vector<DescriptorSp>::iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++)
+               (*desc)->init(context, m_pipelineType);
+
+       // Create descriptor pool
+       {
+               vector<VkDescriptorPoolSize>            poolSizes;
+
+               for (map<VkDescriptorType, deUint32>::iterator i = m_descriptorCounts.begin(); i != m_descriptorCounts.end(); i++)
+               {
+                       const VkDescriptorPoolSize      poolSize        =
+                       {
+                               i->first,       // VkDescriptorType     type
+                               i->second       // deUint32                     descriptorCount
+                       };
+
+                       poolSizes.push_back(poolSize);
+               }
+
+               const VkDescriptorPoolCreateInfo        descriptorPoolCreateInfo        =
+               {
+                       VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,          // VkStructureType                              sType
+                       DE_NULL,                                                                                        // const void*                                  pNext
+                       VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,      // VkDescriptorPoolCreateFlags  flags
+                       (deUint32)m_descriptorSets.size(),                                      // deUint32                                             maxSets
+                       (deUint32)poolSizes.size(),                                                     // deUint32                                             poolSizeCount
+                       poolSizes.data(),                                                                       // const VkDescriptorPoolSize*  pPoolSizes
+               };
+
+               descriptorPool = createDescriptorPool(vk, device, &descriptorPoolCreateInfo);
+       }
+
+       // Create descriptor set layouts. One for each descriptor set used in this test.
+       {
+               for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
+               {
+                       vector<VkDescriptorSetLayoutBinding>    layoutBindings;
+                       const vector<DescriptorSp>&                             bindings        = m_descriptorSets[descriptorSetIdx]->getBindings();
+
+                       for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
+                       {
+                               const VkDescriptorSetLayoutBinding      layoutBinding   =
+                               {
+                                       (deUint32)bindingIdx,                                   // deUint32                             binding
+                                       bindings[bindingIdx]->getType(),                // VkDescriptorType             descriptorType
+                                       bindings[bindingIdx]->getArraySize(),   // deUint32                             descriptorCount
+                                       shaderStage,                                                    // VkShaderStageFlags   stageFlags
+                                       DE_NULL                                                                 // const VkSampler*             pImmutableSamplers
+                               };
+
+                               layoutBindings.push_back(layoutBinding);
+                       }
+
+                       const VkDescriptorSetLayoutCreateInfo   descriptorSetLayoutCreateInfo   =
+                       {
+                               VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,    // VkStructureType                                              sType
+                               DE_NULL,                                                                                                // const void*                                                  pNext
+                               0u,                                                                                                             // VkDescriptorSetLayoutCreateFlags             flags
+                               (deUint32)layoutBindings.size(),                                                // deUint32                                                             bindingCount
+                               layoutBindings.data()                                                                   // const VkDescriptorSetLayoutBinding*  pBindings
+                       };
+
+                       descriptorSetLayouts.push_back(VkDescriptorSetLayoutSp(new Unique<VkDescriptorSetLayout>(createDescriptorSetLayout(vk, device, &descriptorSetLayoutCreateInfo, DE_NULL))));
+               }
+       }
+
+       // Create descriptor sets
+       {
+               for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
+               {
+                       const VkDescriptorSetAllocateInfo       descriptorSetAllocateInfo       =
+                       {
+                               VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,         // VkStructureType                              sType
+                               DE_NULL,                                                                                        // const void*                                  pNext
+                               *descriptorPool,                                                                        // VkDescriptorPool                             descriptorPool
+                               1u,                                                                                                     // deUint32                                             descriptorSetCount
+                               &(descriptorSetLayouts[descriptorSetIdx]->get())        // const VkDescriptorSetLayout* pSetLayouts
+                       };
+
+                       VkDescriptorSet descriptorSet = 0;
+                       VK_CHECK(vk.allocateDescriptorSets(device, &descriptorSetAllocateInfo, &descriptorSet));
+                       descriptorSets.push_back(descriptorSet);
+               }
+       }
+
+       // Descriptor writes and updates
+       {
+               vector<VkWriteDescriptorSet>    descriptorWrites;
+               vector<VkCopyDescriptorSet>             descriptorCopies;
+
+               // Write descriptors that are marked as needing initialization
+               for (size_t descriptorSetIdx = 0; descriptorSetIdx < m_descriptorSets.size(); descriptorSetIdx++)
+               {
+                       const vector<DescriptorSp>& bindings = m_descriptorSets[descriptorSetIdx]->getBindings();
+
+                       for (size_t bindingIdx = 0; bindingIdx < bindings.size(); bindingIdx++)
+                       {
+                               VkWriteDescriptorSet descriptorWrite = bindings[bindingIdx]->getDescriptorWrite();
+
+                               descriptorWrite.dstSet          = descriptorSets[descriptorSetIdx];
+                               descriptorWrite.dstBinding      = (deUint32)bindingIdx;
+
+                               if (descriptorWrite.descriptorCount > 0)
+                                       descriptorWrites.push_back(descriptorWrite);
+                       }
+               }
+
+               for (size_t copyIdx = 0; copyIdx < m_descriptorCopies.size(); copyIdx++)
+               {
+                       const DescriptorCopy            indices = m_descriptorCopies[copyIdx];
+                       const VkCopyDescriptorSet       copy    =
+                       {
+                               VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET,  // VkStructureType      sType
+                               DE_NULL,                                                                // const void*          pNext
+                               descriptorSets[indices.srcSet],                 // VkDescriptorSet      srcSet
+                               indices.srcBinding,                                             // deUint32                     srcBinding
+                               indices.srcArrayElement,                                // deUint32                     srcArrayElement
+                               descriptorSets[indices.dstSet],                 // VkDescriptorSet      dstSet
+                               indices.dstBinding,                                             // deUint32                     dstBinding
+                               indices.dstArrayElement,                                // deUint32                     dstArrayElement
+                               indices.descriptorCount                                 // deUint32                     descriptorCount
+                       };
+
+                       descriptorCopies.push_back(copy);
+               }
+
+               // Update descriptors with writes and copies
+               vk.updateDescriptorSets(device, (deUint32)descriptorWrites.size(), descriptorWrites.data(), (deUint32)descriptorCopies.size(), descriptorCopies.data());
+       }
+
+       // Create pipeline layout
+       {
+               vector<VkDescriptorSetLayout>           descriptorSetLayoutHandles;
+
+               for (size_t i = 0; i < descriptorSetLayouts.size(); i++)
+                       descriptorSetLayoutHandles.push_back(descriptorSetLayouts[i]->get());
+
+               const VkPipelineLayoutCreateInfo        pipelineLayoutCreateInfo        =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,  // VkStructureType                              sType
+                       DE_NULL,                                                                                // const void*                                  pNext
+                       0u,                                                                                             // VkPipelineLayoutCreateFlags  flags
+                       (deUint32)descriptorSetLayoutHandles.size(),    // deUint32                                             setLayoutCount
+                       descriptorSetLayoutHandles.data(),                              // const VkDescriptorSetLayout* pSetLayouts
+                       0u,                                                                                             // deUint32                                             pushConstantRangeCount
+                       DE_NULL                                                                                 // const VkPushConstantRange*   pPushConstantRanges
+               };
+
+               pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
+       }
+
+       if (m_pipelineType == PIPELINE_TYPE_COMPUTE)
+       {
+               // Create compute pipeline
+               {
+                       const Unique<VkShaderModule>                    shaderModule    (createShaderModule(vk, device, context.getBinaryCollection().get("compute"), 0u));
+                       const VkPipelineShaderStageCreateInfo   shaderStageInfo =
+                       {
+                               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                      sType
+                               DE_NULL,                                                                                                // const void*                                          pNext
+                               (VkPipelineShaderStageCreateFlags)0,                                    // VkPipelineShaderStageCreateFlags     flags
+                               VK_SHADER_STAGE_COMPUTE_BIT,                                                    // VkShaderStageFlagBits                        stage
+                               *shaderModule,                                                                                  // VkShaderModule                                       module
+                               "main",                                                                                                 // const char*                                          pName
+                               DE_NULL                                                                                                 // const VkSpecializationInfo*          pSpecializationInfo
+                       };
+
+                       const VkComputePipelineCreateInfo               pipelineInfo    =
+                       {
+                               VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, // VkStructureType                                      sType
+                               DE_NULL,                                                                                // const void*                                          pNext
+                               (VkPipelineCreateFlags)0,                                               // VkPipelineCreateFlags                        flags
+                               shaderStageInfo,                                                                // VkPipelineShaderStageCreateInfo      stage
+                               *pipelineLayout,                                                                // VkPipelineLayout                                     layout
+                               DE_NULL,                                                                                // VkPipeline                                           basePipelineHandle
+                               0                                                                                               // deInt32                                                      basePipelineIndex
+                       };
+
+                       pipeline = createComputePipeline(vk, device, DE_NULL, &pipelineInfo);
+               }
+       }
+       else
+       {
+               // Create result image
+               {
+                       const VkImageCreateInfo imageCreateInfo =
+                       {
+                               VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                            // VkStructureType                      stype
+                               DE_NULL,                                                                                                        // const void*                          pNext
+                               0u,                                                                                                                     // VkImageCreateFlags           flags
+                               VK_IMAGE_TYPE_2D,                                                                                       // VkImageType                          imageType
+                               resultFormat,                                                                                           // VkFormat                                     format
+                               { (deUint32)renderSize.x(), (deUint32)renderSize.y(), 1 },      // VkExtent3D                           extent
+                               1u,                                                                                                                     // deUint32                                     mipLevels
+                               1u,                                                                                                                     // deUint32                                     arrayLayers
+                               VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits        samples
+                               VK_IMAGE_TILING_OPTIMAL,                                                                        // VkImageTiling                        tiling
+                               VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
+                               | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,                                                      // VkImageUsageFlags            usage
+                               VK_SHARING_MODE_EXCLUSIVE,                                                                      // VkSharingMode                        sharingMode
+                               1u,                                                                                                                     // deUint32                                     queueFamilyIndexCount
+                               &queueFamilyIndex,                                                                                      // const deUint32*                      pQueueFamilyIndices
+                               VK_IMAGE_LAYOUT_UNDEFINED,                                                                      // VkImageLayout                        initialLayout
+                       };
+
+                       resultImage = de::MovePtr<ImageWithMemory>(new ImageWithMemory(vk, device, allocator, imageCreateInfo, MemoryRequirement::Any));
+               }
+
+               // Create result image view
+               {
+                       const VkComponentMapping                componentMapping        = makeComponentMappingRGBA();
+
+                       const VkImageSubresourceRange   subresourceRange        =
+                       {
+                               VK_IMAGE_ASPECT_COLOR_BIT,      // VkImageAspectFlags   aspectMask
+                               0u,                                                     // deUint32                             baseMipLevel
+                               1u,                                                     // deUint32                             levelCount
+                               0u,                                                     // deUint32                             baseArrayLayer
+                               1u,                                                     // deUint32                             layerCount
+                       };
+
+                       const VkImageViewCreateInfo             imageViewCreateInfo     =
+                       {
+                               VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType                      sType
+                               DE_NULL,                                                                        // const void*                          pNext
+                               0u,                                                                                     // VkImageViewCreateFlags       flags
+                               **resultImage,                                                          // VkImage                                      image
+                               VK_IMAGE_VIEW_TYPE_2D,                                          // VkImageViewType                      viewType
+                               resultFormat,                                                           // VkFormat                                     format
+                               componentMapping,                                                       // VkComponentMapping           components
+                               subresourceRange                                                        // VkImageSubresourceRange      subresourceRange
+                       };
+
+                       resultImageView = createImageView(vk, device, &imageViewCreateInfo);
+               }
+
+               // Create result buffer
+               {
+                       const VkDeviceSize                      bufferSize                      = renderSize.x() * renderSize.y() * tcu::getPixelSize(mapVkFormat(resultFormat));
+                       const VkBufferCreateInfo        bufferCreateInfo        =
+                       {
+                               VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,   // VkStructureType              sType
+                               DE_NULL,                                                                // const void*                  pNext
+                               0u,                                                                             // VkBufferCreateFlags  flags
+                               bufferSize,                                                             // VkDeviceSize                 size
+                               VK_BUFFER_USAGE_TRANSFER_DST_BIT,               // VkBufferUsageFlags   usage
+                               VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode                sharingMode
+                               0u,                                                                             // uint32_t                             queueFamilyIndexCount
+                               DE_NULL                                                                 // const uint32_t*              pQueueFamilyIndices
+                       };
+
+                       resultImageBuffer = de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
+               }
+
+               // Create render pass
+               {
+                       const VkAttachmentReference             colorAttachmentRef              =
+                       {
+                               0u,                                                                                     // deUint32                     attachment
+                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout        layout
+                       };
+
+                       for (vector<DescriptorSp>::const_iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++)
+                       {
+                               vector<VkAttachmentReference> references = (*desc)->getAttachmentReferences();
+                               inputAttachments.insert(inputAttachments.end(), references.begin(), references.end());
+                       }
+
+                       const VkAttachmentDescription   colorAttachmentDesc             =
+                       {
+                               0u,                                                                                     // VkAttachmentDescriptionFlags flags
+                               VK_FORMAT_R8G8B8A8_UNORM,                                       // VkFormat                                             format
+                               VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits                samples
+                               VK_ATTACHMENT_LOAD_OP_CLEAR,                            // VkAttachmentLoadOp                   loadOp
+                               VK_ATTACHMENT_STORE_OP_STORE,                           // VkAttachmentStoreOp                  storeOp
+                               VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // VkAttachmentLoadOp                   stencilLoadOp
+                               VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // VkAttachmentStoreOp                  stencilStoreOp
+                               VK_IMAGE_LAYOUT_UNDEFINED,                                      // VkImageLayout                                initialLayout
+                               VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL        // VkImageLayout                                finalLayout
+                       };
+
+                       attachmentDescriptions.push_back(colorAttachmentDesc);
+
+                       const VkAttachmentDescription   inputAttachmentDesc             =
+                       {
+                               0u,                                                                                     // VkAttachmentDescriptionFlags flags
+                               VK_FORMAT_R32_SFLOAT,                                           // VkFormat                                             format
+                               VK_SAMPLE_COUNT_1_BIT,                                          // VkSampleCountFlagBits                samples
+                               VK_ATTACHMENT_LOAD_OP_LOAD,                                     // VkAttachmentLoadOp                   loadOp
+                               VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // VkAttachmentStoreOp                  storeOp
+                               VK_ATTACHMENT_LOAD_OP_DONT_CARE,                        // VkAttachmentLoadOp                   stencilLoadOp
+                               VK_ATTACHMENT_STORE_OP_DONT_CARE,                       // VkAttachmentStoreOp                  stencilStoreOp
+                               VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,       // VkImageLayout                                initialLayout
+                               VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL        // VkImageLayout                                finalLayout
+                       };
+
+                       for (size_t inputAttachmentIdx = 0; inputAttachmentIdx < inputAttachments.size(); inputAttachmentIdx++)
+                               attachmentDescriptions.push_back(inputAttachmentDesc);
+
+                       const VkSubpassDescription              subpassDescription              =
+                       {
+                               0u,                                                                                                                             // VkSubpassDescriptionFlags    flags
+                               VK_PIPELINE_BIND_POINT_GRAPHICS,                                                                // VkPipelineBindPoint                  pipelineBindPoint
+                               (deUint32)inputAttachments.size(),                                                              // deUint32                                             inputAttachmentCount
+                               inputAttachments.empty() ? DE_NULL : inputAttachments.data(),   // const VkAttachmentReference* pInputAttachments
+                               1u,                                                                                                                             // deUint32                                             colorAttachmentCount
+                               &colorAttachmentRef,                                                                                    // const VkAttachmentReference* pColorAttachments
+                               DE_NULL,                                                                                                                // const VkAttachmentReference* pResolveAttachments
+                               DE_NULL,                                                                                                                // const VkAttachmentReference* pDepthStencilAttachment
+                               0u,                                                                                                                             // deUint32                                             preserveAttachmentCount
+                               DE_NULL                                                                                                                 // const deUint32*                              pPreserveAttachments
+                       };
+
+                       const VkRenderPassCreateInfo    renderPassCreateInfo    =
+                       {
+                               VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,      // VkStructureType                                      sType
+                               DE_NULL,                                                                        // const void*                                          pNext
+                               0u,                                                                                     // VkRenderPassCreateFlags                      flags
+                               (deUint32)attachmentDescriptions.size(),        // deUint32                                                     attachmentCount
+                               attachmentDescriptions.data(),                          // const VkAttachmentDescription*       pAttachments
+                               1u,                                                                                     // deUint32                                                     subpassCount
+                               &subpassDescription,                                            // const VkSubpassDescription*          pSubpasses
+                               0u,                                                                                     // deUint32                                                     dependencyCount
+                               DE_NULL                                                                         // const VkSubpassDependency*           pDependencies
+                       };
+
+                       renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
+               }
+
+               // Create framebuffer
+               {
+                       imageViews.push_back(*resultImageView);
+
+                       // Add input attachment image views
+                       for (vector<DescriptorSp>::const_iterator desc = m_descriptors.begin(); desc != m_descriptors.end(); desc++)
+                       {
+                               vector<VkImageViewSp> inputAttachmentViews = (*desc)->getImageViews();
+
+                               for (size_t imageViewIdx = 0; imageViewIdx < inputAttachmentViews.size(); imageViewIdx++)
+                                       imageViews.push_back(**inputAttachmentViews[imageViewIdx]);
+                       }
+
+                       const VkFramebufferCreateInfo   framebufferCreateInfo   =
+                       {
+                               VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,      // VkStructureType             sType
+                               DE_NULL,                                                                        // const void*                 pNext
+                               0u,                                                                                     // VkFramebufferCreateFlags    flags
+                               *renderPass,                                                            // VkRenderPass                renderPass
+                               (deUint32)imageViews.size(),                            // deUint32                    attachmentCount
+                               imageViews.data(),                                                      // const VkImageView*          pAttachments
+                               (deUint32)renderSize.x(),                                       // deUint32                    width
+                               (deUint32)renderSize.y(),                                       // deUint32                    height
+                               1u,                                                                                     // deUint32                    layers
+                       };
+
+                       framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
+               }
+
+               // Create graphics pipeline
+               {
+                       const Unique<VkShaderModule>                                    vertexShaderModule              (createShaderModule(vk, device, context.getBinaryCollection().get("vertex"), 0u));
+                       const Unique<VkShaderModule>                                    fragmentShaderModule    (createShaderModule(vk, device, context.getBinaryCollection().get("fragment"), 0u));
+
+                       const VkPipelineVertexInputStateCreateInfo              vertexInputStateParams  =
+                       {
+                               VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                                                      sType
+                               DE_NULL,                                                                                                        // const void*                                                          pNext
+                               (VkPipelineVertexInputStateCreateFlags)0,                                       // VkPipelineVertexInputStateCreateFlags        flags
+                               0u,                                                                                                                     // deUint32                                                                     bindingCount
+                               DE_NULL,                                                                                                        // const VkVertexInputBindingDescription*       pVertexBindingDescriptions
+                               0u,                                                                                                                     // deUint32                                                                     attributeCount
+                               DE_NULL,                                                                                                        // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions
+                       };
+
+                       const std::vector<VkViewport>                                   viewports                               (1, makeViewport(renderSize));
+                       const std::vector<VkRect2D>                                             scissors                                (1, makeRect2D(renderSize));
+
+                       pipeline = makeGraphicsPipeline(vk,                                                                             // const DeviceInterface&                        vk
+                                                                                       device,                                                                 // const VkDevice                                device
+                                                                                       *pipelineLayout,                                                // const VkPipelineLayout                        pipelineLayout
+                                                                                       *vertexShaderModule,                                    // const VkShaderModule                          vertexShaderModule
+                                                                                       DE_NULL,                                                                // const VkShaderModule                          tessellationControlShaderModule
+                                                                                       DE_NULL,                                                                // const VkShaderModule                          tessellationEvalShaderModule
+                                                                                       DE_NULL,                                                                // const VkShaderModule                          geometryShaderModule
+                                                                                       *fragmentShaderModule,                                  // const VkShaderModule                          fragmentShaderModule
+                                                                                       *renderPass,                                                    // const VkRenderPass                            renderPass
+                                                                                       viewports,                                                              // const std::vector<VkViewport>&                viewports
+                                                                                       scissors,                                                               // const std::vector<VkRect2D>&                  scissors
+                                                                                       VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,    // const VkPrimitiveTopology                     topology
+                                                                                       0u,                                                                             // const deUint32                                subpass
+                                                                                       0u,                                                                             // const deUint32                                patchControlPoints
+                                                                                       &vertexInputStateParams);                               // const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
+               }
+       }
+
+       // Run verification shader
+       {
+               const VkPipelineBindPoint       pipelineBindPoint       = m_pipelineType == PIPELINE_TYPE_COMPUTE ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
+               vector<deUint32>                        offsets;
+
+               if (hasDynamicAreas())
+               {
+                       for (size_t areaIdx = 0; areaIdx < m_dynamicAreas.size(); areaIdx++)
+                               offsets.push_back(m_dynamicAreas[areaIdx] * 256u);
+               }
+
+               beginCommandBuffer(vk, *commandBuffer);
+
+               if (m_pipelineType == PIPELINE_TYPE_GRAPHICS)
+               {
+                       const VkRect2D  renderArea  = makeRect2D(renderSize);
+                       const tcu::Vec4 clearColor  (1.0f, 0.0f, 0.0f, 1.0f);
+
+                       beginRenderPass(vk, *commandBuffer, *renderPass, *framebuffer, renderArea, clearColor);
+               }
+
+               vk.cmdBindPipeline(*commandBuffer, pipelineBindPoint, *pipeline);
+               vk.cmdBindDescriptorSets(*commandBuffer, pipelineBindPoint, *pipelineLayout, 0u, (deUint32)descriptorSets.size(), descriptorSets.data(), (deUint32)offsets.size(), offsets.empty() ? DE_NULL : offsets.data());
+
+               if (m_pipelineType == PIPELINE_TYPE_COMPUTE)
+               {
+                       vk.cmdDispatch(*commandBuffer, 1u, 1u, 1u);
+               }
+               else
+               {
+                       vk.cmdDraw(*commandBuffer, 6u, 1u, 0u, 0u);
+                       endRenderPass(vk, *commandBuffer);
+                       copyImageToBuffer(vk, *commandBuffer, **resultImage, resultImageBuffer->get(), renderSize);
+               }
+
+               endCommandBuffer(vk, *commandBuffer);
+               submitCommandsAndWait(vk, device, queue, *commandBuffer);
+       }
+
+       if (m_pipelineType == PIPELINE_TYPE_COMPUTE)
+       {
+               // Invalidate result buffer
+               m_resultBuffer->invalidate(context);
+
+               // Verify result data
+               if (m_resultBuffer->getData()[0] == 1)
+                       return tcu::TestStatus::pass("Pass");
+               else
+                       return tcu::TestStatus::fail("Data validation failed");
+       }
+       else
+       {
+               // Verify result image
+               tcu::ConstPixelBufferAccess     resultBufferAccess(mapVkFormat(resultFormat), renderSize.x(), renderSize.y(), 1, resultImageBuffer->getAllocation().getHostPtr());
+
+               for (deInt32 y = 0; y < renderSize.y(); y++)
+                       for (deInt32 x = 0; x < renderSize.x(); x++)
+                       {
+                               Vec4 pixel = resultBufferAccess.getPixel(x, y, 0);
+
+                               if (pixel.x() != 0.0f || pixel.y() != 1.0f || pixel.z() != 0.0f || pixel.w() != 1.0f)
+                               {
+                                       // Log result image before failing.
+                                       log << tcu::TestLog::ImageSet("Result", "") << tcu::TestLog::Image("Rendered", "Rendered image", resultBufferAccess) << tcu::TestLog::EndImageSet;
+                                       return tcu::TestStatus::fail("Result image validation failed");
+                               }
+                       }
+
+               return tcu::TestStatus::pass("Pass");
+       }
+}
+
+DescriptorCopyTestInstance::DescriptorCopyTestInstance (Context&                               context,
+                                                                                                               DescriptorCommandsSp    commands)
+: vkt::TestInstance    (context)
+, m_commands           (commands)
+{
+}
+
+DescriptorCopyTestInstance::~DescriptorCopyTestInstance (void)
+{
+}
+
+DescriptorCopyTestCase::DescriptorCopyTestCase (tcu::TestContext&              context,
+                                                                                               const char*                             name,
+                                                                                               const char*                             desc,
+                                                                                               DescriptorCommandsSp    commands)
+: vkt::TestCase        (context, name, desc)
+, m_commands   (commands)
+{
+}
+
+DescriptorCopyTestCase::~DescriptorCopyTestCase (void)
+{
+}
+
+void DescriptorCopyTestCase::initPrograms (SourceCollections& programCollection) const
+{
+       if (m_commands->getPipelineType() == PIPELINE_TYPE_COMPUTE)
+       {
+               string computeSrc =
+                       "#version 430\n"
+                       "\n"
+                       + m_commands->getShaderDeclarations() +
+                       "\n"
+                       "void main()\n"
+                       "{\n"
+                       "int result = 1;\n"
+                       + m_commands->getDescriptorVerifications() +
+                       "storageBuffer" + de::toString(m_commands->getResultBufferId()) + ".data = result;\n"
+                       "}\n";
+
+               programCollection.glslSources.add("compute") << glu::ComputeSource(computeSrc);
+       }
+       else
+       {
+               // Produce quad vertices using vertex index
+               string vertexSrc =
+                       "#version 450\n"
+                       "out gl_PerVertex\n"
+                       "{\n"
+                       "    vec4 gl_Position;\n"
+                       "};\n"
+                       "void main()\n"
+                       "{\n"
+                       "    gl_Position = vec4(((gl_VertexIndex + 2) / 3) % 2 == 0 ? -1.0 : 1.0,\n"
+                       "                       ((gl_VertexIndex + 1) / 3) % 2 == 0 ? -1.0 : 1.0, 0.0, 1.0);\n"
+                       "}\n";
+
+               programCollection.glslSources.add("vertex") << glu::VertexSource(vertexSrc);
+
+               string fragmentSrc =
+                       "#version 430\n"
+                       "\n"
+                       + m_commands->getShaderDeclarations() +
+                       "layout (location = 0) out vec4 outColor;\n"
+                       "\n"
+                       "void main()\n"
+                       "{\n"
+                       "int result = 1;\n"
+                       + m_commands->getDescriptorVerifications() +
+                       "if (result == 1) outColor = vec4(0, 1, 0, 1);\n"
+                       "else outColor = vec4(1, 0, 1, 0);\n"
+                       "}\n";
+
+               programCollection.glslSources.add("fragment") << glu::FragmentSource(fragmentSrc);
+       }
+}
+
+TestInstance* DescriptorCopyTestCase::createInstance (Context& context) const
+{
+       return new DescriptorCopyTestInstance(context, m_commands);
+}
+
+tcu::TestStatus DescriptorCopyTestInstance::iterate (void)
+{
+       return m_commands->run(m_context);
+}
+
+template<class T>
+void addDescriptorCopyTests (tcu::TestContext&                                 testCtx,
+                                                        de::MovePtr<tcu::TestCaseGroup>&       group,
+                                                        string                                                         name,
+                                                        PipelineType                                           pipelineType)
+{
+       // Simple test copying inside the same set.
+       {
+               DescriptorCommandsSp commands (new DescriptorCommands(pipelineType));
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 0u);
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 0u);
+
+               commands->copyDescriptor(0u, 0u,        // from
+                                                                0u, 1u);       // to
+
+               vector<deUint32> dynamicAreas;
+               dynamicAreas.push_back(2u);
+               dynamicAreas.push_back(1u);
+               commands->setDynamicAreas(dynamicAreas);
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_0").c_str(), "", commands));
+       }
+
+       // Simple test copying between different sets.
+       {
+               DescriptorCommandsSp commands (new DescriptorCommands(pipelineType));
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 0u);
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 4u)), 1u);
+
+               commands->copyDescriptor(0u, 0u,        // from
+                                                                1u, 0u);       // to
+
+               vector<deUint32> dynamicAreas;
+               dynamicAreas.push_back(0u);
+               dynamicAreas.push_back(1u);
+               commands->setDynamicAreas(dynamicAreas);
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_1").c_str(), "", commands));
+       }
+
+       // Simple test copying between different sets. Destination not updated.
+       {
+               DescriptorCommandsSp commands (new DescriptorCommands(pipelineType));
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 0u);
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 0u, 1u)), 1u);
+
+               commands->copyDescriptor(0u, 0u,        // from
+                                                                1u, 0u);       // to
+
+               vector<deUint32> dynamicAreas;
+               dynamicAreas.push_back(1u);
+               dynamicAreas.push_back(0u);
+               commands->setDynamicAreas(dynamicAreas);
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_2").c_str(), "", commands));
+       }
+
+       // Five sets and several copies.
+       {
+               DescriptorCommandsSp commands (new DescriptorCommands(pipelineType));
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 0u);
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 4u)), 0u);
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 1u);
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 1u)), 1u);
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 1u);
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 5u)), 4u);
+
+               commands->copyDescriptor(4u, 0u,        // from
+                                                                0u, 0u);       // to
+
+               commands->copyDescriptor(0u, 1u,        // from
+                                                                1u, 2u);       // to
+
+               commands->copyDescriptor(0u, 1u,        // from
+                                                                1u, 1u);       // to
+
+               vector<deUint32> dynamicAreas;
+               dynamicAreas.push_back(1u);
+               dynamicAreas.push_back(0u);
+               dynamicAreas.push_back(1u);
+               dynamicAreas.push_back(0u);
+               dynamicAreas.push_back(0u);
+               dynamicAreas.push_back(4u);
+               commands->setDynamicAreas(dynamicAreas);
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_3").c_str(), "", commands));
+       }
+
+       // Several identical copies
+       {
+               DescriptorCommandsSp commands (new DescriptorCommands(pipelineType));
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 0u);
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 4u)), 1u);
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 1u);
+
+               for (deUint32 i = 0; i < 100; i++)
+               {
+                       commands->copyDescriptor(0u, 0u,        // from
+                                                                        1u, 0u);       // to
+               }
+
+               commands->copyDescriptor(1u, 1u,        // from
+                                                                0u, 0u);       // to
+
+               for (deUint32 i = 0; i < 100; i++)
+               {
+                       commands->copyDescriptor(1u, 0u,        // from
+                                                                        1u, 1u);       // to
+               }
+
+               vector<deUint32> dynamicAreas;
+               dynamicAreas.push_back(0u);
+               dynamicAreas.push_back(1u);
+               dynamicAreas.push_back(1u);
+               commands->setDynamicAreas(dynamicAreas);
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_4").c_str(), "", commands));
+       }
+
+       // Copy descriptors back and forth
+       {
+               DescriptorCommandsSp commands (new DescriptorCommands(pipelineType));
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 0u);
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 1u);
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 1u);
+
+               commands->copyDescriptor(0u, 0u,        // from
+                                                                1u, 0u);       // to
+
+               commands->copyDescriptor(1u, 0u,        // from
+                                                                0u, 0u);       // to
+
+               commands->copyDescriptor(1u, 1u,        // from
+                                                                0u, 0u);       // to
+
+               commands->copyDescriptor(1u, 1u,        // from
+                                                                0u, 0u);       // to
+
+               commands->copyDescriptor(1u, 0u,        // from
+                                                                1u, 1u);       // to
+
+               vector<deUint32> dynamicAreas;
+               dynamicAreas.push_back(1u);
+               dynamicAreas.push_back(0u);
+               dynamicAreas.push_back(0u);
+               commands->setDynamicAreas(dynamicAreas);
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_5").c_str(), "", commands));
+       }
+
+       // Copy between non-consecutive descriptor sets
+       {
+               DescriptorCommandsSp commands (new DescriptorCommands(pipelineType));
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 3u)), 0u);
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 5u);
+               commands->addDescriptor(DescriptorSp(new T(1u, 0u, 1u, 2u)), 5u);
+
+               commands->copyDescriptor(0u, 0u,        // from
+                                                                5u, 1u);       // to
+
+               vector<deUint32> dynamicAreas;
+               dynamicAreas.push_back(2u);
+               dynamicAreas.push_back(1u);
+               dynamicAreas.push_back(1u);
+               commands->setDynamicAreas(dynamicAreas);
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_6").c_str(), "", commands));
+       }
+
+       // Simple 3 sized array to 3 sized array inside the same set.
+       {
+               DescriptorCommandsSp commands (new DescriptorCommands(pipelineType));
+               commands->addDescriptor(DescriptorSp(new T(3u, 0u, 3u, 3u)), 0u);
+               commands->addDescriptor(DescriptorSp(new T(3u, 0u, 3u, 4u)), 0u);
+
+               commands->copyDescriptor(0u, 0u, 0u,    // from
+                                                                0u, 0u, 0u,    // to
+                                                                3u);                   // num descriptors
+
+
+               vector<deUint32> dynamicAreas;
+               dynamicAreas.push_back(1u);
+               dynamicAreas.push_back(0u);
+               dynamicAreas.push_back(2u);
+
+               dynamicAreas.push_back(2u);
+               dynamicAreas.push_back(1u);
+               dynamicAreas.push_back(0u);
+               commands->setDynamicAreas(dynamicAreas);
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_array0").c_str(), "", commands));
+       }
+
+       // Simple 2 sized array to 3 sized array into different set.
+       {
+               DescriptorCommandsSp commands (new DescriptorCommands(pipelineType));
+               commands->addDescriptor(DescriptorSp(new T(2u, 0u, 2u, 2u)), 0u);
+               commands->addDescriptor(DescriptorSp(new T(3u, 0u, 3u, 5u)), 1u);
+
+               commands->copyDescriptor(0u, 0u, 0u,    // from
+                                                                1u, 0u, 0u,    // to
+                                                                2u);                   // num descriptors
+
+               vector<deUint32> dynamicAreas;
+               dynamicAreas.push_back(1u);
+               dynamicAreas.push_back(0u);
+
+               dynamicAreas.push_back(1u);
+               dynamicAreas.push_back(0u);
+               dynamicAreas.push_back(1u);
+               commands->setDynamicAreas(dynamicAreas);
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_array1").c_str(), "", commands));
+       }
+
+       // Update array partially with writes and partially with a copy
+       {
+               DescriptorCommandsSp commands (new DescriptorCommands(pipelineType));
+               commands->addDescriptor(DescriptorSp(new T(4u, 0u, 4u, 3u)), 0u);
+               commands->addDescriptor(DescriptorSp(new T(8u, 0u, 5u, 4u)), 0u);
+
+               commands->copyDescriptor(0u, 0u, 1u,    // from
+                                                                0u, 1u, 5u,    // to
+                                                                3u);                   // num descriptors
+
+               vector<deUint32> dynamicAreas;
+               dynamicAreas.push_back(2u);
+               dynamicAreas.push_back(0u);
+               dynamicAreas.push_back(1u);
+               dynamicAreas.push_back(1u);
+
+               dynamicAreas.push_back(2u);
+               dynamicAreas.push_back(0u);
+               dynamicAreas.push_back(1u);
+               dynamicAreas.push_back(2u);
+               dynamicAreas.push_back(0u);
+               dynamicAreas.push_back(1u);
+               dynamicAreas.push_back(1u);
+               dynamicAreas.push_back(2u);
+               commands->setDynamicAreas(dynamicAreas);
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, (name + "_array2").c_str(), "", commands));
+       }
+}
+
+void addSamplerCopyTests (tcu::TestContext&                                    testCtx,
+                                                 de::MovePtr<tcu::TestCaseGroup>&      group,
+                                                 PipelineType                                          pipelineType)
+{
+       // Simple copy between two samplers in the same set
+       {
+               DescriptorCommandsSp    commands        (new DescriptorCommands(pipelineType));
+               SamplerDescriptor*              sampler0        (new SamplerDescriptor());
+               SamplerDescriptor*              sampler1        (new SamplerDescriptor());
+               SampledImageDescriptor* image           (new SampledImageDescriptor());
+               sampler0->addImage(image);
+               sampler1->addImage(image);
+
+               commands->addDescriptor(DescriptorSp(sampler0), 0u);
+               commands->addDescriptor(DescriptorSp(sampler1), 0u);
+               commands->addDescriptor(DescriptorSp(image), 0u);
+
+               commands->copyDescriptor(0u, 0u,        // from
+                                                                0u, 1u);       // to
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, "sampler_0", "", commands));
+       }
+
+       // Simple 3 sized array to 3 sized array inside the same set.
+       {
+               DescriptorCommandsSp    commands        (new DescriptorCommands(pipelineType));
+               SamplerDescriptor*              sampler0        (new SamplerDescriptor(3u, 0u, 3u));
+               // One sampler in between to get the border colors to originally mismatch between sampler0 and sampler1.
+               SamplerDescriptor*              sampler1        (new SamplerDescriptor());
+               SamplerDescriptor*              sampler2        (new SamplerDescriptor(3u, 0u, 3u));
+               SampledImageDescriptor* image           (new SampledImageDescriptor());
+
+               sampler0->addImage(image, 3u);
+               sampler2->addImage(image, 3u);
+
+               commands->addDescriptor(DescriptorSp(sampler0), 0u);
+               commands->addDescriptor(DescriptorSp(sampler1), 0u);
+               commands->addDescriptor(DescriptorSp(sampler2), 0u);
+               commands->addDescriptor(DescriptorSp(image), 0u);
+
+               commands->copyDescriptor(0u, 0u, 0u,    // from
+                                                                0u, 2u, 0u,    // to
+                                                                3u);                   // num descriptors
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, "sampler_array0", "", commands));
+       }
+
+       // Simple 2 sized array to 3 sized array into different set.
+       {
+               DescriptorCommandsSp    commands        (new DescriptorCommands(pipelineType));
+               SamplerDescriptor*              sampler0        (new SamplerDescriptor(2u, 0u, 2u));
+               SamplerDescriptor*              sampler1        (new SamplerDescriptor(3u, 0u, 3u));
+               SampledImageDescriptor* image           (new SampledImageDescriptor());
+
+               sampler0->addImage(image, 2u);
+               sampler1->addImage(image, 3u);
+
+               commands->addDescriptor(DescriptorSp(sampler0), 0u);
+               commands->addDescriptor(DescriptorSp(sampler1), 1u);
+               commands->addDescriptor(DescriptorSp(image), 0u);
+
+               commands->copyDescriptor(0u, 0u, 0u,    // from
+                                                                1u, 0u, 1u,    // to
+                                                                2u);                   // num descriptors
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, "sampler_array1", "", commands));
+       }
+}
+
+void addSampledImageCopyTests (tcu::TestContext&                               testCtx,
+                                                          de::MovePtr<tcu::TestCaseGroup>&     group,
+                                                          PipelineType                                         pipelineType)
+{
+       // Simple copy between two images in the same set
+       {
+               DescriptorCommandsSp    commands        (new DescriptorCommands(pipelineType));
+               SamplerDescriptor*              sampler         (new SamplerDescriptor());
+               SampledImageDescriptor* image0          (new SampledImageDescriptor());
+               SampledImageDescriptor* image1          (new SampledImageDescriptor());
+               image0->addSampler(sampler);
+               image1->addSampler(sampler);
+
+               commands->addDescriptor(DescriptorSp(image0), 0u);
+               commands->addDescriptor(DescriptorSp(image1), 0u);
+               commands->addDescriptor(DescriptorSp(sampler), 0u);
+
+               commands->copyDescriptor(0u, 0u,        // from
+                                                                0u, 1u);       // to
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, "sampled_image_0", "", commands));
+       }
+
+       // Simple 3 sized array to 3 sized array inside the same set.
+       {
+               DescriptorCommandsSp    commands        (new DescriptorCommands(pipelineType));
+               SamplerDescriptor*              sampler         (new SamplerDescriptor());
+               SampledImageDescriptor* image0          (new SampledImageDescriptor(3u, 0u, 3u));
+               SampledImageDescriptor* image1          (new SampledImageDescriptor(3u, 0u, 3u));
+               image0->addSampler(sampler, 3u);
+               image1->addSampler(sampler, 3u);
+
+               commands->addDescriptor(DescriptorSp(sampler), 0u);
+               commands->addDescriptor(DescriptorSp(image0), 0u);
+               commands->addDescriptor(DescriptorSp(image1), 0u);
+
+               commands->copyDescriptor(0u, 1u, 0u,    // from
+                                                                0u, 2u, 0u,    // to
+                                                                3u);                   // num descriptors
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, "sampled_image_array0", "", commands));
+       }
+}
+
+// Mixture of different descriptors in the same test
+void addMixedDescriptorCopyTests (tcu::TestContext&                                    testCtx,
+                                                                 de::MovePtr<tcu::TestCaseGroup>&      group,
+                                                                 PipelineType                                          pipelineType)
+{
+       {
+               DescriptorCommandsSp            commands                (new DescriptorCommands(pipelineType));
+               SamplerDescriptor*                      sampler0                (new SamplerDescriptor());
+               SamplerDescriptor*                      sampler1                (new SamplerDescriptor());
+               SampledImageDescriptor*         image0                  (new SampledImageDescriptor());
+               SampledImageDescriptor*         image1                  (new SampledImageDescriptor());
+               StorageBufferDescriptor*        storageBuffer0  (new StorageBufferDescriptor());
+               StorageBufferDescriptor*        storageBuffer1  (new StorageBufferDescriptor());
+               StorageBufferDescriptor*        storageBuffer2  = new StorageBufferDescriptor();
+               sampler0->addImage(image0);
+               sampler1->addImage(image1);
+
+               commands->addDescriptor(DescriptorSp(sampler0), 0u);            // Set 0, binding 0
+               commands->addDescriptor(DescriptorSp(storageBuffer0), 0u);      // Set 0, binding 1
+               commands->addDescriptor(DescriptorSp(image0), 0u);                      // Set 0, binding 2
+               commands->addDescriptor(DescriptorSp(storageBuffer1), 0u);      // Set 0, binding 3
+               commands->addDescriptor(DescriptorSp(sampler1), 1u);            // Set 1, binding 0
+               commands->addDescriptor(DescriptorSp(image1), 1u);                      // Set 1, binding 1
+               commands->addDescriptor(DescriptorSp(storageBuffer2), 1u);      // Set 1, binding 2
+
+               // image1 to image0
+               commands->copyDescriptor(1u, 1u,        // from
+                                                                0u, 2u);       // to
+
+               // storageBuffer0 to storageBuffer1
+               commands->copyDescriptor(0u, 1u,        // from
+                                                                0u, 3u);       // to
+
+               // storageBuffer1 to storageBuffer2
+               commands->copyDescriptor(0u, 3u,        // from
+                                                                1u, 2u);       // to
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, "mix_0", "", commands));
+       }
+
+       {
+               DescriptorCommandsSp                    commands                                (new DescriptorCommands(pipelineType));
+               StorageTexelBufferDescriptor*   storageTexelBuffer0             (new StorageTexelBufferDescriptor());
+               StorageTexelBufferDescriptor*   storageTexelBuffer1             (new StorageTexelBufferDescriptor());
+               UniformBufferDescriptor*                uniformBuffer0                  (new UniformBufferDescriptor());
+               UniformBufferDescriptor*                uniformBuffer1                  (new UniformBufferDescriptor());
+               UniformBufferDescriptor*                uniformBuffer2                  (new UniformBufferDescriptor());
+               DynamicStorageBufferDescriptor* dynamicStorageBuffer0   (new DynamicStorageBufferDescriptor(1u, 0u, 1u, 3u));
+               DynamicStorageBufferDescriptor* dynamicStorageBuffer1   (new DynamicStorageBufferDescriptor(1u, 0u, 1u, 4u));
+
+               commands->addDescriptor(DescriptorSp(storageTexelBuffer0), 0u);         // Set 0, binding 0
+               commands->addDescriptor(DescriptorSp(uniformBuffer0), 0u);                      // Set 0, binding 1
+               commands->addDescriptor(DescriptorSp(dynamicStorageBuffer0), 0u);       // Set 0, binding 2
+               commands->addDescriptor(DescriptorSp(uniformBuffer1), 0u);                      // Set 0, binding 3
+               commands->addDescriptor(DescriptorSp(dynamicStorageBuffer1), 1u);       // Set 1, binding 0
+               commands->addDescriptor(DescriptorSp(storageTexelBuffer1), 1u);         // Set 1, binding 1
+               commands->addDescriptor(DescriptorSp(uniformBuffer2), 1u);                      // Set 1, binding 2
+
+               vector<deUint32> dynamicAreas;
+               dynamicAreas.push_back(2u);
+               dynamicAreas.push_back(1u);
+               commands->setDynamicAreas(dynamicAreas);
+
+               // uniformBuffer0 to uniformBuffer2
+               commands->copyDescriptor(0u, 1u,        // from
+                                                                1u, 2u);       // to
+
+               // uniformBuffer1 to uniformBuffer2
+               commands->copyDescriptor(0u, 3u,        // from
+                                                                1u, 2u);       // to
+
+               // storageTexelBuffer1 to storageTexelBuffer0
+               commands->copyDescriptor(1u, 1u,        // from
+                                                                0u, 0u);       // to
+
+               // dynamicStorageBuffer0 to dynamicStorageBuffer1
+               commands->copyDescriptor(0u, 2u,        // from
+                                                                1u, 0u);       // to
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, "mix_1", "", commands));
+       }
+
+       if (pipelineType == PIPELINE_TYPE_GRAPHICS)
+       {
+               // Mixture of descriptors, including input attachment.
+               DescriptorCommandsSp                    commands                                (new DescriptorCommands(pipelineType));
+               InputAttachmentDescriptor*              inputAttachment0                (new InputAttachmentDescriptor());
+               InputAttachmentDescriptor*              inputAttachment1                (new InputAttachmentDescriptor());
+               CombinedImageSamplerDescriptor* combinedImageSampler0   (new CombinedImageSamplerDescriptor());
+               CombinedImageSamplerDescriptor* combinedImageSampler1   (new CombinedImageSamplerDescriptor());
+               UniformTexelBufferDescriptor*   uniformTexelBuffer0             (new UniformTexelBufferDescriptor(5u, 0u, 5u));
+               UniformTexelBufferDescriptor*   uniformTexelBuffer1             (new UniformTexelBufferDescriptor(3u, 1u, 1u));
+
+               commands->addDescriptor(DescriptorSp(combinedImageSampler0), 0u);       // Set 0, binding 0
+               commands->addDescriptor(DescriptorSp(inputAttachment0), 0u);            // Set 0, binding 1
+               commands->addDescriptor(DescriptorSp(uniformTexelBuffer0), 0u);         // Set 0, binding 2
+               commands->addDescriptor(DescriptorSp(combinedImageSampler1), 1u);       // Set 1, binding 0
+               commands->addDescriptor(DescriptorSp(inputAttachment1), 1u);            // Set 1, binding 1
+               commands->addDescriptor(DescriptorSp(uniformTexelBuffer1), 1u);         // Set 1, binding 2
+
+               // uniformTexelBuffer0[1..3] to uniformTexelBuffer1[0..2]
+               commands->copyDescriptor(0u, 2u, 1u,    // from
+                                                                1u, 2u, 0u,    // to
+                                                                3u);                   // num descriptors
+
+               // inputAttachment0 to inputAttachment1
+               commands->copyDescriptor(0u, 1u,        // from
+                                                                1u, 1u);       // to
+
+               // combinedImageSampler0 to combinedImageSampler1
+               commands->copyDescriptor(0u, 0u,        // from
+                                                                1u, 0u);       // to
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, "mix_2", "", commands));
+       }
+
+       // Mixture of descriptors using descriptor arrays
+       {
+               DescriptorCommandsSp                    commands                                (new DescriptorCommands(pipelineType));
+               CombinedImageSamplerDescriptor* combinedImageSampler0   (new CombinedImageSamplerDescriptor(3u, 0u, 3u));
+               CombinedImageSamplerDescriptor* combinedImageSampler1   (new CombinedImageSamplerDescriptor(4u, 0u, 2u));
+               CombinedImageSamplerDescriptor* combinedImageSampler2   (new CombinedImageSamplerDescriptor(3u, 0u, 3u));
+               StorageImageDescriptor*                 storageImage0                   (new StorageImageDescriptor(5u, 0u, 5u));
+               StorageImageDescriptor*                 storageImage1                   (new StorageImageDescriptor(3u, 0u, 0u));
+               StorageBufferDescriptor*                storageBuffer0                  (new StorageBufferDescriptor(2u, 0u, 1u));
+               StorageBufferDescriptor*                storageBuffer1                  (new StorageBufferDescriptor(3u, 0u, 3u));
+
+               commands->addDescriptor(DescriptorSp(combinedImageSampler0), 0u);       // Set 0, binding 0
+               commands->addDescriptor(DescriptorSp(storageImage0), 0u);                       // Set 0, binding 1
+               commands->addDescriptor(DescriptorSp(combinedImageSampler1), 0u);       // Set 0, binding 2
+               commands->addDescriptor(DescriptorSp(storageBuffer0), 0u);                      // Set 0, binding 3
+               commands->addDescriptor(DescriptorSp(storageBuffer1), 0u);                      // Set 0, binding 4
+               commands->addDescriptor(DescriptorSp(storageImage1), 1u);                       // Set 1, binding 0
+               commands->addDescriptor(DescriptorSp(combinedImageSampler2), 1u);       // Set 1, binding 1
+
+               // combinedImageSampler0[1..2] to combinedImageSampler1[2..3]
+               commands->copyDescriptor(0u, 0u, 1u,    // from
+                                                                0u, 2u, 2u,    // to
+                                                                2u);                   // num descriptors
+
+               // storageImage0[2..4] to storageImage1[0..2]
+               commands->copyDescriptor(0u, 1u, 2u,    // from
+                                                                1u, 0u, 0u,    // to
+                                                                3u);                   // num descriptors
+
+               // storageBuffer1[1..2] to storageBuffer0[0..1]
+               commands->copyDescriptor(0u, 4u, 1u,    // from
+                                                                0u, 3u, 0u,    // to
+                                                                2u);                   // num descriptors
+
+               commands->addResultBuffer();
+
+               group->addChild(new DescriptorCopyTestCase(testCtx, "mix_array0", "", commands));
+       }
+}
+
+} // anonymous
+
+tcu::TestCaseGroup*    createDescriptorCopyTests (tcu::TestContext& testCtx)
+{
+       de::MovePtr<tcu::TestCaseGroup> descriptorCopyGroup(new tcu::TestCaseGroup(testCtx, "descriptor_copy", "Descriptor copy tests"));
+
+       de::MovePtr<tcu::TestCaseGroup> computeGroup(new tcu::TestCaseGroup(testCtx, "compute", "Compute tests"));
+       de::MovePtr<tcu::TestCaseGroup> graphicsGroup(new tcu::TestCaseGroup(testCtx, "graphics", "Graphics tests"));
+
+       // Compute tests
+       addDescriptorCopyTests<UniformBufferDescriptor>(testCtx, computeGroup, "uniform_buffer", PIPELINE_TYPE_COMPUTE);
+       addDescriptorCopyTests<StorageBufferDescriptor>(testCtx, computeGroup, "storage_buffer", PIPELINE_TYPE_COMPUTE);
+       addDescriptorCopyTests<CombinedImageSamplerDescriptor>(testCtx, computeGroup, "combined_image_sampler", PIPELINE_TYPE_COMPUTE);
+       addDescriptorCopyTests<StorageImageDescriptor>(testCtx, computeGroup, "storage_image", PIPELINE_TYPE_COMPUTE);
+       addDescriptorCopyTests<UniformTexelBufferDescriptor>(testCtx, computeGroup, "uniform_texel_buffer", PIPELINE_TYPE_COMPUTE);
+       addDescriptorCopyTests<StorageTexelBufferDescriptor>(testCtx, computeGroup, "storage_texel_buffer", PIPELINE_TYPE_COMPUTE);
+       addDescriptorCopyTests<DynamicUniformBufferDescriptor>(testCtx, computeGroup, "uniform_buffer_dynamic", PIPELINE_TYPE_COMPUTE);
+       addDescriptorCopyTests<DynamicStorageBufferDescriptor>(testCtx, computeGroup, "storage_buffer_dynamic", PIPELINE_TYPE_COMPUTE);
+       addSamplerCopyTests(testCtx, computeGroup, PIPELINE_TYPE_COMPUTE);
+       addSampledImageCopyTests(testCtx, computeGroup, PIPELINE_TYPE_COMPUTE);
+       addMixedDescriptorCopyTests(testCtx, computeGroup, PIPELINE_TYPE_COMPUTE);
+
+       // Graphics tests
+       addDescriptorCopyTests<UniformBufferDescriptor>(testCtx, graphicsGroup, "uniform_buffer", PIPELINE_TYPE_GRAPHICS);
+       addDescriptorCopyTests<StorageBufferDescriptor>(testCtx, graphicsGroup, "storage_buffer", PIPELINE_TYPE_GRAPHICS);
+       addDescriptorCopyTests<CombinedImageSamplerDescriptor>(testCtx, graphicsGroup, "combined_image_sampler", PIPELINE_TYPE_GRAPHICS);
+       addDescriptorCopyTests<StorageImageDescriptor>(testCtx, graphicsGroup, "storage_image", PIPELINE_TYPE_GRAPHICS);
+       addDescriptorCopyTests<InputAttachmentDescriptor>(testCtx, graphicsGroup, "input_attachment", PIPELINE_TYPE_GRAPHICS);
+       addDescriptorCopyTests<UniformTexelBufferDescriptor>(testCtx, graphicsGroup, "uniform_texel_buffer", PIPELINE_TYPE_GRAPHICS);
+       addDescriptorCopyTests<StorageTexelBufferDescriptor>(testCtx, graphicsGroup, "storage_texel_buffer", PIPELINE_TYPE_GRAPHICS);
+       addDescriptorCopyTests<DynamicUniformBufferDescriptor>(testCtx, graphicsGroup, "uniform_buffer_dynamic", PIPELINE_TYPE_GRAPHICS);
+       addDescriptorCopyTests<DynamicStorageBufferDescriptor>(testCtx, graphicsGroup, "storage_buffer_dynamic", PIPELINE_TYPE_GRAPHICS);
+       addSamplerCopyTests(testCtx, graphicsGroup, PIPELINE_TYPE_GRAPHICS);
+       addSampledImageCopyTests(testCtx, graphicsGroup, PIPELINE_TYPE_GRAPHICS);
+       addMixedDescriptorCopyTests(testCtx, graphicsGroup, PIPELINE_TYPE_GRAPHICS);
+
+       descriptorCopyGroup->addChild(computeGroup.release());
+       descriptorCopyGroup->addChild(graphicsGroup.release());
+
+       return descriptorCopyGroup.release();
+}
+
+}      // BindingModel
+}      // vkt
diff --git a/external/vulkancts/modules/vulkan/binding_model/vktBindingDescriptorCopyTests.hpp b/external/vulkancts/modules/vulkan/binding_model/vktBindingDescriptorCopyTests.hpp
new file mode 100644 (file)
index 0000000..d5844a4
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _VKTBINDINGDESCRIPTORCOPYTESTS_HPP
+#define _VKTBINDINGDESCRIPTORCOPYTESTS_HPP
+/*-------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2019 Google Inc.
+ * Copyright (c) 2019 The Khronos Group Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *//*!
+ * \file
+ * \brief Tests for descriptor copying
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tcuTestCase.hpp"
+
+namespace vkt
+{
+namespace BindingModel
+{
+
+tcu::TestCaseGroup* createDescriptorCopyTests (tcu::TestContext& testCtx);
+
+} // BindingModel
+} // vkt
+
+#endif // _VKTBINDINGDESCRIPTORCOPYTESTS_HPP
index 0340f68..39c3ce1 100644 (file)
@@ -26,6 +26,7 @@
 #include "vktBindingShaderAccessTests.hpp"
 #include "vktBindingDescriptorUpdateTests.hpp"
 #include "vktBindingDescriptorSetRandomTests.hpp"
+#include "vktBindingDescriptorCopyTests.hpp"
 #include "vktTestGroupUtil.hpp"
 
 namespace vkt
@@ -43,6 +44,7 @@ void createChildren (tcu::TestCaseGroup* group)
        group->addChild(createShaderAccessTests(testCtx));
        group->addChild(createDescriptorUpdateTests(testCtx));
        group->addChild(createDescriptorSetRandomTests(testCtx));
+       group->addChild(createDescriptorCopyTests(testCtx));
 
        // \todo [2015-07-30 jarkko] .change_binding.{between_renderpasses, within_pass}
        // \todo [2015-07-30 jarkko] .descriptor_set_chain
index 202b4dd..18f0fd8 100644 (file)
@@ -222911,6 +222911,193 @@ dEQP-VK.binding_model.descriptorset_random.sets32.runtimesize.ubolimithigh.sboli
 dEQP-VK.binding_model.descriptorset_random.sets32.runtimesize.ubolimithigh.sbolimithigh.imglimithigh.iublimithigh.comp.0
 dEQP-VK.binding_model.descriptorset_random.sets32.runtimesize.ubolimithigh.sbolimithigh.imglimithigh.iublimithigh.frag.0
 dEQP-VK.binding_model.descriptorset_random.sets32.runtimesize.ubolimithigh.sbolimithigh.imglimithigh.iublimithigh.vert.0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_2
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_3
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_4
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_5
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_6
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_3
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_4
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_5
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_6
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_0
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_1
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_2
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_3
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_4
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_5
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_6
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_array0
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_array1
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_array2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_3
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_4
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_5
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_6
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_array0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_array1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_array2
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_2
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_3
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_4
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_5
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_6
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_3
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_4
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_5
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_6
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_2
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_3
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_4
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_5
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_6
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_array0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_array1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_array2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_3
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_4
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_5
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_6
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_array0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_array1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_array2
+dEQP-VK.binding_model.descriptor_copy.compute.sampler_0
+dEQP-VK.binding_model.descriptor_copy.compute.sampler_array0
+dEQP-VK.binding_model.descriptor_copy.compute.sampler_array1
+dEQP-VK.binding_model.descriptor_copy.compute.sampled_image_0
+dEQP-VK.binding_model.descriptor_copy.compute.sampled_image_array0
+dEQP-VK.binding_model.descriptor_copy.compute.mix_0
+dEQP-VK.binding_model.descriptor_copy.compute.mix_1
+dEQP-VK.binding_model.descriptor_copy.compute.mix_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_2
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_3
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_4
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_5
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_6
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_3
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_4
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_5
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_6
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_0
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_1
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_2
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_3
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_4
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_5
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_6
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_3
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_4
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_5
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_6
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_0
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_1
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_2
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_3
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_4
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_5
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_6
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_2
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_3
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_4
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_5
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_6
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_3
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_4
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_5
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_6
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_2
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_3
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_4
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_5
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_6
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_3
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_4
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_5
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_6
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.sampler_0
+dEQP-VK.binding_model.descriptor_copy.graphics.sampler_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.sampler_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.sampled_image_0
+dEQP-VK.binding_model.descriptor_copy.graphics.sampled_image_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.mix_0
+dEQP-VK.binding_model.descriptor_copy.graphics.mix_1
+dEQP-VK.binding_model.descriptor_copy.graphics.mix_2
+dEQP-VK.binding_model.descriptor_copy.graphics.mix_array0
 dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_0_compute
 dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_1_compute
 dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_2_compute
index 8a4e8dc..fcaa09e 100644 (file)
@@ -222911,6 +222911,193 @@ dEQP-VK.binding_model.descriptorset_random.sets32.runtimesize.ubolimithigh.sboli
 dEQP-VK.binding_model.descriptorset_random.sets32.runtimesize.ubolimithigh.sbolimithigh.imglimithigh.iublimithigh.comp.0
 dEQP-VK.binding_model.descriptorset_random.sets32.runtimesize.ubolimithigh.sbolimithigh.imglimithigh.iublimithigh.frag.0
 dEQP-VK.binding_model.descriptorset_random.sets32.runtimesize.ubolimithigh.sbolimithigh.imglimithigh.iublimithigh.vert.0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_2
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_3
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_4
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_5
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_6
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_3
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_4
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_5
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_6
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_0
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_1
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_2
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_3
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_4
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_5
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_6
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_array0
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_array1
+dEQP-VK.binding_model.descriptor_copy.compute.combined_image_sampler_array2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_3
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_4
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_5
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_6
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_array0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_array1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_image_array2
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_2
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_3
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_4
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_5
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_6
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_texel_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_3
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_4
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_5
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_6
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_texel_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_2
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_3
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_4
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_5
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_6
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_array0
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_array1
+dEQP-VK.binding_model.descriptor_copy.compute.uniform_buffer_dynamic_array2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_2
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_3
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_4
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_5
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_6
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_array0
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_array1
+dEQP-VK.binding_model.descriptor_copy.compute.storage_buffer_dynamic_array2
+dEQP-VK.binding_model.descriptor_copy.compute.sampler_0
+dEQP-VK.binding_model.descriptor_copy.compute.sampler_array0
+dEQP-VK.binding_model.descriptor_copy.compute.sampler_array1
+dEQP-VK.binding_model.descriptor_copy.compute.sampled_image_0
+dEQP-VK.binding_model.descriptor_copy.compute.sampled_image_array0
+dEQP-VK.binding_model.descriptor_copy.compute.mix_0
+dEQP-VK.binding_model.descriptor_copy.compute.mix_1
+dEQP-VK.binding_model.descriptor_copy.compute.mix_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_2
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_3
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_4
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_5
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_6
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_3
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_4
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_5
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_6
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_0
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_1
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_2
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_3
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_4
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_5
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_6
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.combined_image_sampler_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_3
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_4
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_5
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_6
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_image_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_0
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_1
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_2
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_3
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_4
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_5
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_6
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.input_attachment_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_2
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_3
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_4
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_5
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_6
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_texel_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_3
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_4
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_5
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_6
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_texel_buffer_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_2
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_3
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_4
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_5
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_6
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.uniform_buffer_dynamic_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_2
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_3
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_4
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_5
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_6
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.storage_buffer_dynamic_array2
+dEQP-VK.binding_model.descriptor_copy.graphics.sampler_0
+dEQP-VK.binding_model.descriptor_copy.graphics.sampler_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.sampler_array1
+dEQP-VK.binding_model.descriptor_copy.graphics.sampled_image_0
+dEQP-VK.binding_model.descriptor_copy.graphics.sampled_image_array0
+dEQP-VK.binding_model.descriptor_copy.graphics.mix_0
+dEQP-VK.binding_model.descriptor_copy.graphics.mix_1
+dEQP-VK.binding_model.descriptor_copy.graphics.mix_2
+dEQP-VK.binding_model.descriptor_copy.graphics.mix_array0
 dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_0_compute
 dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_1_compute
 dEQP-VK.spirv_assembly.instruction.compute.spirv_version.1_2_compute