Merge 28-push-constant-tests
authorPyry Haulos <phaulos@google.com>
Wed, 16 Dec 2015 19:09:15 +0000 (11:09 -0800)
committerPyry Haulos <phaulos@google.com>
Wed, 16 Dec 2015 19:11:44 +0000 (11:11 -0800)
Change-Id: I781593486ced28860e5aff2649505ad4060b4b6d

1  2 
external/vulkancts/modules/vulkan/pipeline/vktPipelinePushConstantTests.cpp

index 0000000,4afb9ab..dd2beb2
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1574 +1,1574 @@@
 -                      DE_ASSERT(!"Range size unsupported yet");
+ /*------------------------------------------------------------------------
+  * Vulkan Conformance Tests
+  * ------------------------
+  *
+  * Copyright (c) 2015 The Khronos Group Inc.
+  * Copyright (c) 2015 ARM Limited.
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a
+  * copy of this software and/or associated documentation files (the
+  * "Materials"), to deal in the Materials without restriction, including
+  * without limitation the rights to use, copy, modify, merge, publish,
+  * distribute, sublicense, and/or sell copies of the Materials, and to
+  * permit persons to whom the Materials are furnished to do so, subject to
+  * the following conditions:
+  *
+  * The above copyright notice(s) and this permission notice shall be included
+  * in all copies or substantial portions of the Materials.
+  *
+  * The Materials are Confidential Information as defined by the
+  * Khronos Membership Agreement until designated non-confidential by Khronos,
+  * at which point this condition clause shall be removed.
+  *
+  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+  * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+  *
+  *//*!
+  * \file
+  * \brief PushConstant Tests
+  *//*--------------------------------------------------------------------*/
+ #include "vktPipelinePushConstantTests.hpp"
+ #include "vktPipelineClearUtil.hpp"
+ #include "vktPipelineImageUtil.hpp"
+ #include "vktPipelineVertexUtil.hpp"
+ #include "vktPipelineReferenceRenderer.hpp"
+ #include "vktTestCase.hpp"
+ #include "vkImageUtil.hpp"
+ #include "vkMemUtil.hpp"
+ #include "vkPrograms.hpp"
+ #include "vkQueryUtil.hpp"
+ #include "vkRef.hpp"
+ #include "vkRefUtil.hpp"
+ #include "vkBuilderUtil.hpp"
+ #include "vkTypeUtil.hpp"
+ #include "tcuImageCompare.hpp"
+ #include "deMemory.h"
+ #include "deRandom.hpp"
+ #include "deStringUtil.hpp"
+ #include "deUniquePtr.hpp"
+ #include <algorithm>
+ #include <sstream>
+ #include <vector>
+ namespace vkt
+ {
+ namespace pipeline
+ {
+ using namespace vk;
+ namespace
+ {
+ enum
+ {
+       TRIANGLE_COUNT  = 2,
+       MAX_RANGE_COUNT = 5
+ };
+ enum RangeSizeCase
+ {
+       SIZE_CASE_4     = 0,
+       SIZE_CASE_16,
+       SIZE_CASE_40,
+       SIZE_CASE_128,
+       SIZE_CASE_UNSUPPORTED
+ };
+       
+ struct PushConstantData
+ {
+       struct PushConstantRange
+       {
+               VkShaderStageFlags              shaderStage;
+               deUint32                                offset;
+               deUint32                                size;
+       } range;
+       struct PushConstantUpdate
+       {
+               deUint32                                offset;
+               deUint32                                size;
+       } update;
+ };
+ class PushConstantGraphicsTest : public vkt::TestCase
+ {
+ public:
+                                                       PushConstantGraphicsTest        (tcu::TestContext&                      testContext,
+                                                                                                                const std::string&                     name,
+                                                                                                                const std::string&                     description,
+                                                                                                                const deUint32                         rangeCount,
+                                                                                                                const PushConstantData         pushConstantRange[MAX_RANGE_COUNT],
+                                                                                                                const deBool                           multipleUpdate);
+       virtual                                 ~PushConstantGraphicsTest       (void);
+       virtual void                    initPrograms                            (SourceCollections& sourceCollections) const;
+       virtual TestInstance*   createInstance                          (Context& context) const;
+       RangeSizeCase                   getRangeSizeCase                        (deUint32 rangeSize) const;
+ private:
+       const deUint32                  m_rangeCount;
+       PushConstantData                m_pushConstantRange[MAX_RANGE_COUNT];
+       const deBool                    m_multipleUpdate;
+ };
+ class PushConstantGraphicsTestInstance : public vkt::TestInstance
+ {
+ public:
+                                                               PushConstantGraphicsTestInstance        (Context&                                       context,
+                                                                                                                                        const deUint32                         rangeCount,
+                                                                                                                                        const PushConstantData         pushConstantRange[MAX_RANGE_COUNT],
+                                                                                                                                        const deBool                           multipleUpdate);
+       virtual                                         ~PushConstantGraphicsTestInstance       (void);
+       virtual tcu::TestStatus         iterate                                                         (void);
+       
+       void                                            createShaderStage                                       (const DeviceInterface&         vk,
+                                                                                                                                        VkDevice                                       device,
+                                                                                                                                        const BinaryCollection&        programCollection,
+                                                                                                                                        const char*                            name,
+                                                                                                                                        VkShaderStageFlagBits          stage,
+                                                                                                                                        Move<VkShaderModule>*          module);
+       std::vector<Vertex4RGBA>        createQuad                                                      (const float size);
+       
+ private:
+       tcu::TestStatus                         verifyImage                                                     (void);
+ private:
+       const tcu::IVec2                                                                m_renderSize;
+       const VkFormat                                                                  m_colorFormat;
+       const deUint32                                                                  m_rangeCount;
+       PushConstantData                                                                m_pushConstantRange[MAX_RANGE_COUNT];
+       const deBool                                                                    m_multipleUpdate;
+       VkImageCreateInfo                                                               m_colorImageCreateInfo;
+       Move<VkImage>                                                                   m_colorImage;
+       de::MovePtr<Allocation>                                                 m_colorImageAlloc;
+       Move<VkImageView>                                                               m_colorAttachmentView;
+       Move<VkRenderPass>                                                              m_renderPass;
+       Move<VkFramebuffer>                                                             m_framebuffer;
+       Move<VkShaderModule>                                                    m_vertexShaderModule;
+       Move<VkShaderModule>                                                    m_fragmentShaderModule;
+       Move<VkShaderModule>                                                    m_geometryShaderModule;
+       Move<VkShaderModule>                                                    m_tessControlShaderModule;
+       Move<VkShaderModule>                                                    m_tessEvaluationShaderModule;
+       VkShaderStageFlags                                                              m_shaderFlags;
+       std::vector<VkPipelineShaderStageCreateInfo>    m_shaderStage;
+       Move<VkBuffer>                                                                  m_vertexBuffer;
+       std::vector<Vertex4RGBA>                                                m_vertices;
+       de::MovePtr<Allocation>                                                 m_vertexBufferAlloc;
+       Move<VkBuffer>                                                                  m_uniformBuffer;
+       de::MovePtr<Allocation>                                                 m_uniformBufferAlloc;
+       Move<VkDescriptorPool>                                                  m_descriptorPool;
+       Move<VkDescriptorSetLayout>                                             m_descriptorSetLayout;
+       Move<VkDescriptorSet>                                                   m_descriptorSet;
+       
+       Move<VkPipelineLayout>                                                  m_pipelineLayout;
+       Move<VkPipeline>                                                                m_graphicsPipelines;
+       Move<VkCommandPool>                                                             m_cmdPool;
+       Move<VkCommandBuffer>                                                   m_cmdBuffer;
+       Move<VkFence>                                                                   m_fence;
+ };
+ PushConstantGraphicsTest::PushConstantGraphicsTest (tcu::TestContext&                 testContext,
+                                                                                                       const std::string&                      name,
+                                                                                                       const std::string&                      description,
+                                                                                                       const deUint32                          rangeCount,
+                                                                                                       const PushConstantData          pushConstantRange[MAX_RANGE_COUNT],
+                                                                                                       const deBool                            multipleUpdate)
+       : vkt::TestCase         (testContext, name, description)
+       , m_rangeCount          (rangeCount)
+       , m_multipleUpdate      (multipleUpdate)
+ {
+       deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
+ }
+ PushConstantGraphicsTest::~PushConstantGraphicsTest (void)
+ {
+ }
+ TestInstance* PushConstantGraphicsTest::createInstance (Context& context) const
+ {
+       return new PushConstantGraphicsTestInstance(context, m_rangeCount, m_pushConstantRange, m_multipleUpdate);
+ }
+ RangeSizeCase PushConstantGraphicsTest::getRangeSizeCase (deUint32 rangeSize) const
+ {
+       switch (rangeSize)
+       {
+               case 4:
+                       return SIZE_CASE_4;
+               case 16:
+                       return SIZE_CASE_16;
+               case 40:
+                       return SIZE_CASE_40;
+               case 128:
+                       return SIZE_CASE_128;
+               default:
 -                                      DE_ASSERT(!"Not implemented yet");
++                      DE_FATAL("Range size unsupported yet");
+                       return SIZE_CASE_UNSUPPORTED;
+       }
+ }
+ void PushConstantGraphicsTest::initPrograms (SourceCollections& sourceCollections) const
+ {
+       std::ostringstream      vertexSrc;
+       std::ostringstream      fragmentSrc;
+       std::ostringstream      geometrySrc;
+       std::ostringstream      tessControlSrc;
+       std::ostringstream      tessEvaluationSrc;
+       
+       for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
+       {
+               if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
+               {
+                       vertexSrc << "#version 450\n"
+                                         << "layout(location = 0) in highp vec4 position;\n"
+                                         << "layout(location = 1) in highp vec4 color;\n"
+                                         << "layout(location = 0) out highp vec4 vtxColor;\n"
+                                         << "layout(push_constant) uniform Material {\n";
+                 
+                       switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
+                       {
+                               case SIZE_CASE_4:
+                                       vertexSrc << "int kind;\n"
+                                                         << "} matInst;\n";
+                                       break;
+                               case SIZE_CASE_16:
+                                       vertexSrc << "vec4 color;\n"
+                                                         << "} matInst;\n"
+                                                         << "layout(location = 0) uniform UniformBuf {\n"
+                                                         << "vec4 element;\n"
+                                                         << "} uniformBuf;\n";
+                                       break;
+                               case SIZE_CASE_40:
+                                       vertexSrc << "int kind;\n"
+                                                         << "vec4 color;\n"
+                                                         << "} matInst[2];\n";
+                                       break;
+                               case SIZE_CASE_128:
+                                       vertexSrc << "vec4 color[8];\n"
+                                                         << "} matInst;\n";
+                                       break;
+                               default:
 -                                      DE_ASSERT(!"Not implemented yet");
++                                      DE_FATAL("Not implemented yet");
+                                       break;
+                       }
+                 
+                       vertexSrc << "void main()\n"
+                                         << "{\n"
+                                         << "  gl_Position = position;\n";
+                 
+                       switch (getRangeSizeCase(m_pushConstantRange[rangeNdx].range.size))
+                       {
+                               case SIZE_CASE_4:
+                                       vertexSrc << "switch (matInst.kind) {\n"
+                                                         << "case 0: vtxColor = vec4(0.0, 1.0, 0, 1.0); break;\n"
+                                                         << "case 1: vtxColor = vec4(0.0, 0.0, 1.0, 1.0); break;\n"
+                                                         << "case 2: vtxColor = vec4(1.0, 0.0, 0, 1.0); break;\n"
+                                                         << "default: vtxColor = color; break;}\n"
+                                                         << "}\n"; 
+                                       break;
+                               case SIZE_CASE_16:
+                                       vertexSrc << "vtxColor = (matInst.color + uniformBuf.element) * 0.5;\n"
+                                                         << "}\n";
+                                       break;
+                               case SIZE_CASE_40:
+                                       vertexSrc << "vtxColor = matInst[1].color;\n"
+                                                         << "}\n";
+                                       break;
+                               case SIZE_CASE_128:
+                                       vertexSrc << "vec4 color = vec4(0.0, 0, 0, 0.0);\n"
+                                                         << "for (int i = 0; i < 8; i++)\n"
+                                                         << "{\n"
+                                                         << "  color = color + matInst.color[i];\n"
+                                                         << "}\n"
+                                                         << "vtxColor = color * 0.125;\n"
+                                                         << "}\n";
+                                       break;
+                               default:
++                                      DE_FATAL("Not implemented yet");
+                                       break;
+                       }
+                       
+                       sourceCollections.glslSources.add("color_vert") << glu::VertexSource(vertexSrc.str());
+               }
+               
+               if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
+               {
+                       tessControlSrc << "#version 450\n"
+                                                  << "layout (vertices = 3) out;\n"
+                                                  << "layout(push_constant) uniform TessLevel {\n"
+                                                  << "    layout(offset = 24) int level;\n"
+                                                  << "} tessLevel;\n"
+                                                  << "in highp vec4 color[];\n"
+                                                  << "out highp vec4 vtxColor[];\n"
+                                                  << "void main()\n"
+                                                  << "{\n"
+                                                  << "  gl_TessLevelInner[0] = tessLevel.level;\n"
+                                                  << "  gl_TessLevelOuter[0] = tessLevel.level;\n"
+                                                  << "  gl_TessLevelOuter[1] = tessLevel.level;\n"
+                                                  << "  gl_TessLevelOuter[2] = tessLevel.level;\n"
+                                                  << "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+                                                  << "  vtxColor[gl_InvocationID] = color[gl_InvocationID];\n"
+                                                  << "}\n";
+                                               
+                       sourceCollections.glslSources.add("color_tesc") << glu::TessellationControlSource(tessControlSrc.str());
+               }
+               
+               if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
+               {
+                       tessEvaluationSrc << "#version 450\n"
+                                                         << "layout (triangles) in;\n"
+                                                         << "layout(push_constant) uniform Material {\n"
+                                                         << "    layout(offset = 28) vec4 color;\n"
+                                                         << "} matInst;\n"
+                                                         << "in highp vec4 color[];\n"
+                                                         << "out highp vec4 vtxColor;\n"
+                                                         << "void main()\n"
+                                                         << "{\n"
+                                                         << "  gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position;\n"
+                                                         << "  vtxColor = matInst.color;\n"
+                                                         << "}\n";
+                                               
+                       sourceCollections.glslSources.add("color_tese") << glu::TessellationEvaluationSource(tessEvaluationSrc.str());
+               }
+               
+               if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
+               {
+                       geometrySrc << "#version 450\n"
+                                               << "layout(triangles) in;\n"
+                                               << "layout(triangle_strip, max_vertices=3) out;\n"
+                                               << "layout(push_constant) uniform Material {\n"
+                                               << "    layout(offset = 20) int kind;\n"
+                                               << "} matInst;\n"
+                                               << "in highp vec4 color[];\n"
+                                               << "out highp vec4 vtxColor;\n"
+                                               << "void main()\n"
+                                               << "{\n"
+                                               << "  for(int i=0; i<3; i++)\n"
+                                               << "  {\n"
+                                               << "    gl_Position.xyz = gl_in[i].gl_Position.xyz / matInst.kind;\n"
+                                               << "    gl_Position.w = gl_in[i].gl_Position.w;\n"
+                                               << "    vtxColor = color[i];\n"
+                                               << "    EmitVertex();\n"
+                                               << "  }\n"
+                                               << "  EndPrimitive();\n"
+                                               << "}\n";
+                                               
+                       sourceCollections.glslSources.add("color_geom") << glu::GeometrySource(geometrySrc.str());
+               }
+               
+               if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_FRAGMENT_BIT)
+               {
+                       fragmentSrc << "#version 450\n"
+                                               << "layout(location = 0) in highp vec4 vtxColor;\n"
+                                               << "layout(location = 0) out highp vec4 fragColor;\n"
+                                               << "layout(push_constant) uniform Material {\n";
+                                               
+                       if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_VERTEX_BIT)
+                       {
+                               fragmentSrc << "    layout(offset = 0) int kind;\n"
+                                                       << "} matInst;\n";
+                       }
+                       else
+                       {
+                               fragmentSrc << "    layout(offset = 16) int kind;\n"
+                                                       << "} matInst;\n";
+                       }
+                                               
+                       fragmentSrc << "void main (void)\n"
+                                               << "{\n"
+                                               << "    switch (matInst.kind) {\n"
+                                               << "    case 0: fragColor = vec4(0, 1.0, 0, 1.0); break;\n"
+                                               << "    case 1: fragColor = vec4(0, 0.0, 1.0, 1.0); break;\n"
+                                               << "    case 2: fragColor = vtxColor; break;\n"
+                                               << "    default: fragColor = vec4(1.0, 1.0, 1.0, 1.0); break;}\n"
+                                               << "}\n";
+                                               
+                       sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSrc.str());
+               }
+       }
+       
+       // add a pass through fragment shader if it's not activated in push constant ranges
+       if (fragmentSrc.str().empty())
+       {
+               fragmentSrc << "#version 450\n"
+                                       << "layout(location = 0) in highp vec4 vtxColor;\n"
+                                       << "layout(location = 0) out highp vec4 fragColor;\n"
+                                       << "void main (void)\n"
+                                       << "{\n"
+                                       << "    fragColor = vtxColor;\n"
+                                       << "}\n";
+                   
+               sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(fragmentSrc.str());
+       }
+ }
+ void PushConstantGraphicsTestInstance::createShaderStage (const DeviceInterface&      vk,
+                                                                                                                 VkDevice                                      device,
+                                                                                                                 const BinaryCollection&       programCollection,
+                                                                                                                 const char*                           name,
+                                                                                                                 VkShaderStageFlagBits         stage,
+                                                                                                                 Move<VkShaderModule>*         module)
+ {
+       *module = createShaderModule(vk, device, programCollection.get(name), 0);
+       
+       const vk::VkPipelineShaderStageCreateInfo       stageCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
+               DE_NULL,                                                                                                // const void*                                                  pNext;
+               0u,                                                                                                             // VkPipelineShaderStageCreateFlags             flags;
+               stage,                                                                                                  // VkShaderStageFlagBits                                stage;
+               **module,                                                                                               // VkShaderModule                                               module;
+               "main",                                                                                                 // const char*                                                  pName;
+               DE_NULL                                                                                                 // const VkSpecializationInfo*                  pSpecializationInfo;
+       };
+       
+       m_shaderStage.push_back(stageCreateInfo);
+ }
+ std::vector<Vertex4RGBA> PushConstantGraphicsTestInstance::createQuad(const float size)
+ {
+       std::vector<Vertex4RGBA>        vertices;
+       
+       const tcu::Vec4                         color                           = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
+       const Vertex4RGBA                       lowerLeftVertex         = {tcu::Vec4(-size, -size, 0.0f, 1.0f), color};
+       const Vertex4RGBA                       lowerRightVertex        = {tcu::Vec4(size, -size, 0.0f, 1.0f), color};
+       const Vertex4RGBA                       UpperLeftVertex         = {tcu::Vec4(-size, size, 0.0f, 1.0f), color};
+       const Vertex4RGBA                       UpperRightVertex        = {tcu::Vec4(size, size, 0.0f, 1.0f), color};
+       
+       vertices.push_back(lowerLeftVertex);
+       vertices.push_back(lowerRightVertex);
+       vertices.push_back(UpperLeftVertex);
+       vertices.push_back(UpperLeftVertex);
+       vertices.push_back(lowerRightVertex);
+       vertices.push_back(UpperRightVertex);
+       
+       return vertices;
+ }
+ PushConstantGraphicsTestInstance::PushConstantGraphicsTestInstance (Context&                                  context,
+                                                                                                                                       const deUint32                          rangeCount,
+                                                                                                                                       const PushConstantData          pushConstantRange[MAX_RANGE_COUNT],
+                                                                                                                                       deBool                                          multipleUpdate)
+       : vkt::TestInstance             (context)
+       , m_renderSize                  (32, 32)
+       , m_colorFormat                 (VK_FORMAT_R8G8B8A8_UNORM)
+       , m_rangeCount                  (rangeCount)
+       , m_multipleUpdate              (multipleUpdate)
+       , m_shaderFlags                 (VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT)
+ {
+       const DeviceInterface&          vk                                              = context.getDeviceInterface();
+       const VkDevice                          vkDevice                                = context.getDevice();
+       const deUint32                          queueFamilyIndex                = context.getUniversalQueueFamilyIndex();
+       SimpleAllocator                         memAlloc                                (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
+       const VkComponentMapping        componentMappingRGBA    = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
+       deMemcpy(m_pushConstantRange, pushConstantRange, sizeof(PushConstantData) * MAX_RANGE_COUNT);
+       
+       // Create color image
+       {
+               const VkImageCreateInfo colorImageParams =
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                                                            // VkStructureType                      sType;
+                       DE_NULL,                                                                                                                                        // const void*                          pNext;
+                       0u,                                                                                                                                                     // VkImageCreateFlags           flags;
+                       VK_IMAGE_TYPE_2D,                                                                                                                       // VkImageType                          imageType;
+                       m_colorFormat,                                                                                                                          // VkFormat                                     format;
+                       { m_renderSize.x(), m_renderSize.y(), 1u },                                                                     // 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;
+               };
+               m_colorImageCreateInfo  = colorImageParams;
+               m_colorImage                    = createImage(vk, vkDevice, &m_colorImageCreateInfo);
+               // Allocate and bind color image memory
+               m_colorImageAlloc               = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
+               VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
+       }
+       // Create color attachment view
+       {
+               const VkImageViewCreateInfo colorAttachmentViewParams =
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,                       // VkStructureType                              sType;
+                       DE_NULL,                                                                                        // const void*                                  pNext;
+                       0u,                                                                                                     // VkImageViewCreateFlags               flags;
+                       *m_colorImage,                                                                          // VkImage                                              image;
+                       VK_IMAGE_VIEW_TYPE_2D,                                                          // VkImageViewType                              viewType;
+                       m_colorFormat,                                                                          // VkFormat                                             format;
+                       componentMappingRGBA,                                                           // VkChannelMapping                             channels;
+                       { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },          // VkImageSubresourceRange              subresourceRange;
+               };
+               m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
+       }
+       // Create render pass
+       {
+               const VkAttachmentDescription colorAttachmentDescription =
+               {
+                       0u,                                                                                                     // VkAttachmentDescriptionFlags         flags;
+                       m_colorFormat,                                                                          // 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_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                                        initialLayout;
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout                                        finalLayout;
+               };
+               const VkAttachmentDescription attachments[1] =
+               {
+                       colorAttachmentDescription
+               };
+               const VkAttachmentReference colorAttachmentReference =
+               {
+                       0u,                                                                                                     // deUint32                     attachment;
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL                        // VkImageLayout        layout;
+               };
+               
+               const VkAttachmentReference depthAttachmentReference =
+               {
+                       VK_ATTACHMENT_UNUSED,                                                           // deUint32                     attachment;
+                       VK_IMAGE_LAYOUT_UNDEFINED                                                       // VkImageLayout        layout;
+               };
+               const VkSubpassDescription subpassDescription =
+               {
+                       0u,                                                                                                     // VkSubpassDescriptionFlags            flags;
+                       VK_PIPELINE_BIND_POINT_GRAPHICS,                                        // VkPipelineBindPoint                          pipelineBindPoint;
+                       0u,                                                                                                     // deUint32                                                     inputAttachmentCount;
+                       DE_NULL,                                                                                        // const VkAttachmentReference*         pInputAttachments;
+                       1u,                                                                                                     // deUint32                                                     colorAttachmentCount;
+                       &colorAttachmentReference,                                                      // const VkAttachmentReference*         pColorAttachments;
+                       DE_NULL,                                                                                        // const VkAttachmentReference*         pResolveAttachments;
+                       &depthAttachmentReference,                                                      // const VkAttachmentReference*         pDepthStencilAttachment;
+                       0u,                                                                                                     // deUint32                                                     preserveAttachmentCount;
+                       DE_NULL                                                                                         // const VkAttachmentReference*         pPreserveAttachments;
+               };
+               const VkRenderPassCreateInfo renderPassParams =
+               {
+                       VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,                      // VkStructureType                                      sType;
+                       DE_NULL,                                                                                        // const void*                                          pNext;
+                       0u,                                                                                                     // VkRenderPassCreateFlags                      flags;
+                       1u,                                                                                                     // deUint32                                                     attachmentCount;
+                       attachments,                                                                            // const VkAttachmentDescription*       pAttachments;
+                       1u,                                                                                                     // deUint32                                                     subpassCount;
+                       &subpassDescription,                                                            // const VkSubpassDescription*          pSubpasses;
+                       0u,                                                                                                     // deUint32                                                     dependencyCount;
+                       DE_NULL                                                                                         // const VkSubpassDependency*           pDependencies;
+               };
+               m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
+       }
+       // Create framebuffer
+       {
+               const VkImageView attachmentBindInfos[1] =
+               {
+                 *m_colorAttachmentView
+               };
+               const VkFramebufferCreateInfo framebufferParams =
+               {
+                       VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,                      // VkStructureType                              sType;
+                       DE_NULL,                                                                                        // const void*                                  pNext;
+                       0u,                                                                                                     // VkFramebufferCreateFlags             flags;
+                       *m_renderPass,                                                                          // VkRenderPass                                 renderPass;
+                       1u,                                                                                                     // deUint32                                             attachmentCount;
+                       attachmentBindInfos,                                                            // const VkImageView*                   pAttachments;
+                       (deUint32)m_renderSize.x(),                                                     // deUint32                                             width;
+                       (deUint32)m_renderSize.y(),                                                     // deUint32                                             height;
+                       1u                                                                                                      // deUint32                                             layers;
+               };
+               m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
+       }
+       // Create pipeline layout
+       {
+               // create push constant range
+               VkPushConstantRange     pushConstantRanges[MAX_RANGE_COUNT];
+               for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
+               {
+                       pushConstantRanges[rangeNdx].stageFlags = m_pushConstantRange[rangeNdx].range.shaderStage;
+                       pushConstantRanges[rangeNdx].offset             = m_pushConstantRange[rangeNdx].range.offset;
+                       pushConstantRanges[rangeNdx].size               = m_pushConstantRange[rangeNdx].range.size;
+               }
+               
+               // create descriptor set layout
+               m_descriptorSetLayout = DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT).build(vk, vkDevice);
+               
+               // create descriptor pool
+               m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1u).build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+               
+               // create uniform buffer
+               const VkBufferCreateInfo uniformBufferCreateInfo =
+               {
+                       VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                                           // VkStructureType              sType;
+                       DE_NULL,                                                                                                        // const void*                  pNext;
+                       16u,                                                                                                            // VkDeviceSize                 size;
+                       VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,                                                     // VkBufferUsageFlags   usage;
+                       0u,                                                                                                                     // VkBufferCreateFlags  flags;
+                       VK_SHARING_MODE_EXCLUSIVE,                                                                      // VkSharingMode                sharingMode;
+                       1u,                                                                                                                     // deUint32                             queueFamilyCount;
+                       &queueFamilyIndex                                                                                       // const deUint32*              pQueueFamilyIndices;
+               };
+               
+               m_uniformBuffer                 = createBuffer(vk, vkDevice, &uniformBufferCreateInfo);
+               m_uniformBufferAlloc    = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_uniformBuffer), MemoryRequirement::HostVisible);
+               VK_CHECK(vk.bindBufferMemory(vkDevice, *m_uniformBuffer, m_uniformBufferAlloc->getMemory(), m_uniformBufferAlloc->getOffset()));
+               
+               tcu::Vec4       value   = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
+               deMemcpy(m_uniformBufferAlloc->getHostPtr(), &value, 16u);
+               flushMappedMemoryRange(vk, vkDevice, m_uniformBufferAlloc->getMemory(), m_uniformBufferAlloc->getOffset(), 16u);
+               
+               // create and update descriptor set
+               const VkDescriptorSetAllocateInfo allocInfo =
+               {
+                       VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,                         // VkStructureType                             sType;
+                       DE_NULL,                                                                                                        // const void*                                 pNext;
+                       *m_descriptorPool,                                                                                      // VkDescriptorPool                            descriptorPool;
+                       1u,                                                                                                                     // uint32_t                                    setLayoutCount;
+                       &(*m_descriptorSetLayout),                                                                      // const VkDescriptorSetLayout*                pSetLayouts;
+               };
+               m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
+               
+               const VkDescriptorBufferInfo descriptorInfo = makeDescriptorBufferInfo(*m_uniformBuffer, (VkDeviceSize)0u, (VkDeviceSize)16u);
+               
+               DescriptorSetUpdateBuilder()
+                       .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &descriptorInfo)
+                       .update(vk, vkDevice);
+               
+               // create pipeline layout
+               const VkPipelineLayoutCreateInfo        pipelineLayoutParams    =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
+                       DE_NULL,                                                                                        // const void*                                  pNext;
+                       0u,                                                                                                     // VkPipelineLayoutCreateFlags  flags;
+                       1u,                                                                                                     // deUint32                                             descriptorSetCount;
+                       &(*m_descriptorSetLayout),                                                      // const VkDescriptorSetLayout* pSetLayouts;
+                       m_rangeCount,                                                                           // deUint32                                             pushConstantRangeCount;
+                       pushConstantRanges                                                                      // const VkPushConstantRange*   pPushConstantRanges;
+               };
+               
+               m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
+       }
+       // Create shaders
+       {
+               for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
+               {
+                       if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_GEOMETRY_BIT)
+                       {
+                               m_shaderFlags |= VK_SHADER_STAGE_GEOMETRY_BIT;
+                       }
+                       if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
+                       {
+                               m_shaderFlags |= VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
+                       }
+                       if (m_pushConstantRange[rangeNdx].range.shaderStage & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
+                       {
+                               m_shaderFlags |= VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
+                       }
+               }
+               
+               VkPhysicalDeviceFeatures features = m_context.getDeviceFeatures();
+               
+               createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_vert", VK_SHADER_STAGE_VERTEX_BIT , &m_vertexShaderModule);
+               if (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT || m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
+               {
+                       if (features.tessellationShader == VK_FALSE)
+                       {
+                               TCU_THROW(NotSupportedError, "Tessellation Not Supported");
+                       }
+                       createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_tesc", VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, &m_tessControlShaderModule);
+                       createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_tese", VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, &m_tessEvaluationShaderModule);
+               }
+               if (m_shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
+               {
+                       if (features.geometryShader == VK_FALSE)
+                       {
+                               TCU_THROW(NotSupportedError, "Geometry Not Supported");
+                       }
+                       createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_geom", VK_SHADER_STAGE_GEOMETRY_BIT, &m_geometryShaderModule);
+               }
+               createShaderStage(vk, vkDevice, m_context.getBinaryCollection(), "color_frag", VK_SHADER_STAGE_FRAGMENT_BIT, &m_fragmentShaderModule);
+       }
+       // Create pipeline
+       {
+               const VkVertexInputBindingDescription vertexInputBindingDescription =
+               {
+                       0u,                                                                             // deUint32                                     binding;
+                       sizeof(Vertex4RGBA),                                    // deUint32                                     strideInBytes;
+                       VK_VERTEX_INPUT_RATE_VERTEX                             // VkVertexInputStepRate        stepRate;
+               };
+               const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] =
+               {
+                       {
+                               0u,                                                                     // deUint32     location;
+                               0u,                                                                     // deUint32     binding;
+                               VK_FORMAT_R32G32B32A32_SFLOAT,          // VkFormat     format;
+                               0u                                                                      // deUint32     offsetInBytes;
+                       }
+               };
+               const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                                                // const void*                                                          pNext;
+                       0u,                                                                                                                             // vkPipelineVertexInputStateCreateFlags        flags;
+                       1u,                                                                                                                             // deUint32                                                                     bindingCount;
+                       &vertexInputBindingDescription,                                                                 // const VkVertexInputBindingDescription*       pVertexBindingDescriptions;
+                       1u,                                                                                                                             // deUint32                                                                     attributeCount;
+                       vertexInputAttributeDescriptions                                                                // const VkVertexInputAttributeDescription*     pVertexAttributeDescriptions;
+               };
+               const VkPrimitiveTopology topology = (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+               const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                                                // const void*                                                          pNext;
+                       (VkPipelineInputAssemblyStateCreateFlags)0u,                                    // VkPipelineInputAssemblyStateCreateFlags      flags;
+                       topology,                                                                                                               // VkPrimitiveTopology                                          topology;
+                       false                                                                                                                   // VkBool32                                                                     primitiveRestartEnable;
+               };
+               const VkViewport viewport =
+               {
+                       0.0f,                                           // float        originX;
+                       0.0f,                                           // float        originY;
+                       (float)m_renderSize.x(),        // float        width;
+                       (float)m_renderSize.y(),        // float        height;
+                       0.0f,                                           // float        minDepth;
+                       1.0f                                            // float        maxDepth;
+               };
+               const VkRect2D scissor = { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } };
+               const VkPipelineViewportStateCreateInfo viewportStateParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,                  // VkStructureType                                              sType;
+                       DE_NULL,                                                                                                                // const void*                                                  pNext;
+                       (VkPipelineViewportStateCreateFlags)0u,                                                 // VkPipelineViewportStateCreateFlags   flags;
+                       1u,                                                                                                                             // deUint32                                                             viewportCount;
+                       &viewport,                                                                                                              // const VkViewport*                                    pViewports;
+                       1u,                                                                                                                             // deUint32                                                             scissorCount;
+                       &scissor,                                                                                                               // const VkRect2D*                                              pScissors;
+               };
+               
+               const VkPipelineRasterizationStateCreateInfo rasterStateParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                                                // const void*                                                          pNext;
+                       0u,                                                                                                                             // VkPipelineRasterizationStateCreateFlags      flags;
+                       false,                                                                                                                  // VkBool32                                                                     depthClampEnable;
+                       false,                                                                                                                  // VkBool32                                                                     rasterizerDiscardEnable;
+                       VK_POLYGON_MODE_FILL,                                                                                   // VkPolygonMode                                                        polygonMode;
+                       VK_CULL_MODE_NONE,                                                                                              // VkCullModeFlags                                                      cullMode;
+                       VK_FRONT_FACE_COUNTER_CLOCKWISE,                                                                // VkFrontFace                                                          frontFace;
+                       VK_FALSE,                                                                                                               // VkBool32                                                                     depthBiasEnable;
+                       0.0f,                                                                                                                   // float                                                                        depthBiasConstantFactor;
+                       0.0f,                                                                                                                   // float                                                                        depthBiasClamp;
+                       0.0f,                                                                                                                   // float                                                                        depthBiasSlopeFactor;
+                       1.0f,                                                                                                                   // float                                                                        lineWidth;
+               };
+               const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
+               {
+                       false,                                                                                                                  // VkBool32                                     blendEnable;
+                       VK_BLEND_FACTOR_ONE,                                                                                    // VkBlendFactor                        srcColorBlendFactor;
+                       VK_BLEND_FACTOR_ZERO,                                                                                   // VkBlendFactor                        dstColorBlendFactor;
+                       VK_BLEND_OP_ADD,                                                                                                // VkBlendOp                            colorBlendOp;
+                       VK_BLEND_FACTOR_ONE,                                                                                    // VkBlendFactor                        srcAlphaBlendFactor;
+                       VK_BLEND_FACTOR_ZERO,                                                                                   // VkBlendFactor                        dstAlphaBlendFactor;
+                       VK_BLEND_OP_ADD,                                                                                                // VkBlendOp                            alphaBlendOp;
+                       VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |                   // VkColorComponentFlags        colorWriteMask;
+                               VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
+               };
+               const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,       // VkStructureType                                                              sType;
+                       DE_NULL,                                                                                                        // const void*                                                                  pNext;
+                       0,                                                                                                                      // VkPipelineColorBlendStateCreateFlags                 flags;
+                       false,                                                                                                          // VkBool32                                                                             logicOpEnable;
+                       VK_LOGIC_OP_COPY,                                                                                       // VkLogicOp                                                                    logicOp;
+                       1u,                                                                                                                     // deUint32                                                                             attachmentCount;
+                       &colorBlendAttachmentState,                                                                     // const VkPipelineColorBlendAttachmentState*   pAttachments;
+                       { 0.0f, 0.0f, 0.0f, 0.0f },                                                                     // float                                                                                blendConstants[4];
+               };
+               const VkPipelineMultisampleStateCreateInfo      multisampleStateParams  =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,       // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                                        // const void*                                                          pNext;
+                       0u,                                                                                                                     // VkPipelineMultisampleStateCreateFlags        flags;
+                       VK_SAMPLE_COUNT_1_BIT,                                                                          // VkSampleCountFlagBits                                        rasterizationSamples;
+                       false,                                                                                                          // VkBool32                                                                     sampleShadingEnable;
+                       0.0f,                                                                                                           // float                                                                        minSampleShading;
+                       DE_NULL,                                                                                                        // const VkSampleMask*                                          pSampleMask;
+                       false,                                                                                                          // VkBool32                                                                     alphaToCoverageEnable;
+                       false                                                                                                           // VkBool32                                                                     alphaToOneEnable;
+               };
+               
+               const VkPipelineDynamicStateCreateInfo dynamicStateParams               =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,           // VkStructureType                                              sType;
+                       DE_NULL,                                                                                                        // const void*                                                  pNext;
+                       0u,                                                                                                                     // VkPipelineDynamicStateCreateFlags    flags;
+                       0u,                                                                                                                     // deUint32                                                             dynamicStateCount;
+                       DE_NULL                                                                                                         // const VkDynamicState*                                pDynamicStates;
+               };
+               
+               VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,     // VkStructureType                                                      sType;
+                       DE_NULL,                                                                                                        // const void*                                                          pNext;
+                       0u,                                                                                                                     // VkPipelineDepthStencilStateCreateFlags       flags;
+                       false,                                                                                                          // VkBool32                                                                     depthTestEnable;
+                       false,                                                                                                          // VkBool32                                                                     depthWriteEnable;
+                       VK_COMPARE_OP_LESS,                                                                                     // VkCompareOp                                                          depthCompareOp;
+                       false,                                                                                                          // VkBool32                                                                     depthBoundsTestEnable;
+                       false,                                                                                                          // VkBool32                                                                     stencilTestEnable;
+                       // VkStencilOpState     front;
+                       {
+                               VK_STENCIL_OP_KEEP,             // VkStencilOp  stencilFailOp;
+                               VK_STENCIL_OP_KEEP,             // VkStencilOp  stencilPassOp;
+                               VK_STENCIL_OP_KEEP,             // VkStencilOp  stencilDepthFailOp;
+                               VK_COMPARE_OP_NEVER,    // VkCompareOp  stencilCompareOp;
+                               0u,                                             // deUint32             stencilCompareMask;
+                               0u,                                             // deUint32             stencilWriteMask;
+                               0u,                                             // deUint32             stencilReference;
+                       },
+                       // VkStencilOpState     back;
+                       {
+                               VK_STENCIL_OP_KEEP,             // VkStencilOp  stencilFailOp;
+                               VK_STENCIL_OP_KEEP,             // VkStencilOp  stencilPassOp;
+                               VK_STENCIL_OP_KEEP,             // VkStencilOp  stencilDepthFailOp;
+                               VK_COMPARE_OP_NEVER,    // VkCompareOp  stencilCompareOp;
+                               0u,                                             // deUint32             stencilCompareMask;
+                               0u,                                             // deUint32             stencilWriteMask;
+                               0u,                                             // deUint32             stencilReference;
+                       },
+                       -1.0f,                                                                                                          // float                        minDepthBounds;
+                       +1.0f,                                                                                                          // float                        maxDepthBounds;
+               };
+               const VkPipelineTessellationStateCreateInfo tessellationStateParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,              // VkStructureType                             sType;
+                       DE_NULL,                                                                                                                // const void*                                 pNext;
+                       0u,                                                                                                                             // VkPipelineTesselationStateCreateFlags       flags;
+                       3u,                                                                                                                             // uint32_t                                    patchControlPoints;
+               };
+               const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
+               {
+                       VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,        // VkStructureType                                                                      sType;
+                       DE_NULL,                                                                                        // const void*                                                                          pNext;
+                       0u,                                                                                                     // VkPipelineCreateFlags                                                        flags;
+                       (deUint32)m_shaderStage.size(),                                         // deUint32                                                                                     stageCount;
+                       &m_shaderStage[0],                                                                      // const VkPipelineShaderStageCreateInfo*                       pStages;
+                       &vertexInputStateParams,                                                        // const VkPipelineVertexInputStateCreateInfo*          pVertexInputState;
+                       &inputAssemblyStateParams,                                                      // const VkPipelineInputAssemblyStateCreateInfo*        pInputAssemblyState;
+                       (m_shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT ? &tessellationStateParams: DE_NULL),                 // const VkPipelineTessellationStateCreateInfo*         pTessellationState;
+                       &viewportStateParams,                                                           // const VkPipelineViewportStateCreateInfo*                     pViewportState;
+                       &rasterStateParams,                                                                     // const VkPipelineRasterStateCreateInfo*                       pRasterState;
+                       &multisampleStateParams,                                                        // const VkPipelineMultisampleStateCreateInfo*          pMultisampleState;
+                       &depthStencilStateParams,                                                       // const VkPipelineDepthStencilStateCreateInfo*         pDepthStencilState;
+                       &colorBlendStateParams,                                                         // const VkPipelineColorBlendStateCreateInfo*           pColorBlendState;
+                       &dynamicStateParams,                                                            // const VkPipelineDynamicStateCreateInfo*                      pDynamicState;
+                       *m_pipelineLayout,                                                                      // VkPipelineLayout                                                                     layout;
+                       *m_renderPass,                                                                          // VkRenderPass                                                                         renderPass;
+                       0u,                                                                                                     // deUint32                                                                                     subpass;
+                       0u,                                                                                                     // VkPipeline                                                                           basePipelineHandle;
+                       0u                                                                                                      // deInt32                                                                                      basePipelineIndex;
+               };
+               m_graphicsPipelines = createGraphicsPipeline(vk, vkDevice, DE_NULL, &graphicsPipelineParams);
+       }
+       // Create vertex buffer
+       {
+               m_vertices                      = createQuad(1.0f);
+               
+               const VkBufferCreateInfo vertexBufferParams =
+               {
+                       VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                                           // VkStructureType              sType;
+                       DE_NULL,                                                                                                        // const void*                  pNext;
+                       0u,                                                                                                                     // VkBufferCreateFlags  flags;
+                       (VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()),        // VkDeviceSize                 size;
+                       VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,                                                      // VkBufferUsageFlags   usage;
+                       VK_SHARING_MODE_EXCLUSIVE,                                                                      // VkSharingMode                sharingMode;
+                       1u,                                                                                                                     // deUint32                             queueFamilyCount;
+                       &queueFamilyIndex                                                                                       // const deUint32*              pQueueFamilyIndices;
+               };
+               
+               m_vertexBuffer          = createBuffer(vk, vkDevice, &vertexBufferParams);
+               m_vertexBufferAlloc     = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
+               VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
+               // Load vertices into vertex buffer
+               deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
+               flushMappedMemoryRange(vk, vkDevice, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset(), vertexBufferParams.size);
+       }
+       // Create command pool
+       {
+               const VkCommandPoolCreateInfo cmdPoolParams =
+               {
+                       VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,     // VkStructureType              sType;
+                       DE_NULL,                                                                        // const void*                  pNext;
+                       VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,           // VkCmdPoolCreateFlags flags;
+                       queueFamilyIndex                                                        // deUint32                             queueFamilyIndex;
+               };
+               m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
+       }
+       // Create command buffer
+       {
+               const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
+               {
+                       VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType                      sType;
+                       DE_NULL,                                                                                // const void*                          pNext;
+                       *m_cmdPool,                                                                             // VkCommandPool                        commandPool;
+                       VK_COMMAND_BUFFER_LEVEL_PRIMARY,                                // VkCommandBufferLevel         level;
+                       1u                                                                                              // deUint32                                     bufferCount;
+               };
+               const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+               {
+                       VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                                      sType;
+                       DE_NULL,                                                                                // const void*                                          pNext;
+                       0u,                                                                                             // VkCommandBufferUsageFlags            flags;
+                       DE_NULL,                                                                                // VkRenderPass                                         renderPass;
+                       0u,                                                                                             // deUint32                                                     subpass;
+                       DE_NULL,                                                                                // VkFramebuffer                                        framebuffer;
+                       false,                                                                                  // VkBool32                                                     occlusionQueryEnable;
+                       0u,                                                                                             // VkQueryControlFlags                          queryFlags;
+                       0u                                                                                              // VkQueryPipelineStatisticFlags        pipelineStatistics;
+               };
+               const VkClearValue attachmentClearValues[] =
+               {
+                       defaultClearValue(m_colorFormat)
+               };
+               const VkRenderPassBeginInfo renderPassBeginInfo =
+               {
+                       VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,                               // VkStructureType              sType;
+                       DE_NULL,                                                                                                // const void*                  pNext;
+                       *m_renderPass,                                                                                  // VkRenderPass                 renderPass;
+                       *m_framebuffer,                                                                                 // VkFramebuffer                framebuffer;
+                       { { 0, 0 } , { m_renderSize.x(), m_renderSize.y() } },  // VkRect2D                             renderArea;
+                       1,                                                                                                              // deUint32                             clearValueCount;
+                       attachmentClearValues                                                                   // const VkClearValue*  pClearValues;
+               };
+               m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
+               VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
+               vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+               // update push constant
+               std::vector<tcu::Vec4> color(8, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
+               std::vector<tcu::Vec4> allOnes(8, tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
+               
+               const deUint32  kind    = 2u;
+               const void*     value   = DE_NULL;
+               for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
+               {
+                       value = (m_pushConstantRange[rangeNdx].range.size == 4u) ? (void*)(&kind) : (void*)(&color[0]);
+                               
+                       vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange[rangeNdx].range.shaderStage, m_pushConstantRange[rangeNdx].range.offset, m_pushConstantRange[rangeNdx].range.size, value);
+                       
+                       if (m_pushConstantRange[rangeNdx].update.size < m_pushConstantRange[rangeNdx].range.size)
+                       {
+                               value = (void*)(&allOnes[0]);
+                               vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange[rangeNdx].range.shaderStage, m_pushConstantRange[rangeNdx].update.offset, m_pushConstantRange[rangeNdx].update.size, value);
+                       }
+               }
+               
+               // draw quad
+               const VkDeviceSize      triangleOffset  = (m_vertices.size() / TRIANGLE_COUNT) * sizeof(Vertex4RGBA);
+               for (int triangleNdx = 0; triangleNdx < TRIANGLE_COUNT; triangleNdx++)
+               {
+                       VkDeviceSize vertexBufferOffset = triangleOffset * triangleNdx;
+                       
+                       if (m_multipleUpdate)
+                       {
+                               vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange[0].range.shaderStage, m_pushConstantRange[0].range.offset, m_pushConstantRange[0].range.size, &triangleNdx);
+                       }
+                       vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelines);
+                       vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
+                       vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
+                       
+                       vk.cmdDraw(*m_cmdBuffer, (deUint32)(m_vertices.size() / TRIANGLE_COUNT), 1, 0, 0);
+               }
+               vk.cmdEndRenderPass(*m_cmdBuffer);
+               VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
+       }
+       // Create fence
+       {
+               const VkFenceCreateInfo fenceParams =
+               {
+                       VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    // VkStructureType              sType;
+                       DE_NULL,                                                                // const void*                  pNext;
+                       0u                                                                              // VkFenceCreateFlags   flags;
+               };
+               m_fence = createFence(vk, vkDevice, &fenceParams);
+       }
+ }
+ PushConstantGraphicsTestInstance::~PushConstantGraphicsTestInstance (void)
+ {
+ }
+ tcu::TestStatus PushConstantGraphicsTestInstance::iterate (void)
+ {
+       const DeviceInterface&          vk                      = m_context.getDeviceInterface();
+       const VkDevice                          vkDevice        = m_context.getDevice();
+       const VkQueue                           queue           = m_context.getUniversalQueue();
+       const VkSubmitInfo                      submitInfo      =
+       {
+               VK_STRUCTURE_TYPE_SUBMIT_INFO,  // VkStructureType                      sType;
+               DE_NULL,                                                // const void*                          pNext;
+               0u,                                                             // deUint32                                     waitSemaphoreCount;
+               DE_NULL,                                                // const VkSemaphore*           pWaitSemaphores;
+               1u,                                                             // deUint32                                     commandBufferCount;
+               &m_cmdBuffer.get(),                             // const VkCommandBuffer*       pCommandBuffers;
+               0u,                                                             // deUint32                                     signalSemaphoreCount;
+               DE_NULL                                                 // const VkSemaphore*           pSignalSemaphores;
+       };
+       VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
+       VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
+       VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
+       return verifyImage();
+ }
+ tcu::TestStatus PushConstantGraphicsTestInstance::verifyImage (void)
+ {
+       const tcu::TextureFormat        tcuColorFormat  = mapVkFormat(m_colorFormat);
+       const tcu::TextureFormat        tcuDepthFormat  = tcu::TextureFormat();
+       const ColorVertexShader         vertexShader;
+       const ColorFragmentShader       fragmentShader  (tcuColorFormat, tcuDepthFormat);
+       const rr::Program                       program                 (&vertexShader, &fragmentShader);
+       ReferenceRenderer                       refRenderer             (m_renderSize.x(), m_renderSize.y(), 1, tcuColorFormat, tcuDepthFormat, &program);
+       bool                                            compareOk               = false;
+       // Render reference image
+       {
+               if (m_shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
+               {
+                       m_vertices = createQuad(0.5f);
+               }
+               
+               for (size_t rangeNdx = 0; rangeNdx < m_rangeCount; rangeNdx++)
+               {
+                       if (m_pushConstantRange[rangeNdx].update.size < m_pushConstantRange[rangeNdx].range.size)
+                       {
+                               for (size_t vertexNdx = 0; vertexNdx < m_vertices.size(); vertexNdx++)
+                               {
+                                       m_vertices[vertexNdx].color.xyzw() = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
+                               }
+                       }
+               }
+               
+               if (m_multipleUpdate)
+               {
+                       for (size_t vertexNdx = 0; vertexNdx < 3; vertexNdx++)
+                       {
+                               m_vertices[vertexNdx].color.xyz() = tcu::Vec3(0.0f, 1.0f, 0.0f);
+                       }
+                       for (size_t vertexNdx = 3; vertexNdx < m_vertices.size(); vertexNdx++)
+                       {
+                               m_vertices[vertexNdx].color.xyz() = tcu::Vec3(0.0f, 0.0f, 1.0f);
+                       }
+               }
+               
+               for (int triangleNdx = 0; triangleNdx < TRIANGLE_COUNT; triangleNdx++)
+               {
+                       rr::RenderState renderState(refRenderer.getViewportState());
+                       
+                       refRenderer.draw(renderState,
+                                                        rr::PRIMITIVETYPE_TRIANGLES,
+                                                        std::vector<Vertex4RGBA>(m_vertices.begin() + triangleNdx * 3,
+                                                                                                         m_vertices.begin() + (triangleNdx + 1) * 3));
+               }
+       }
+       // Compare result with reference image
+       {
+               const DeviceInterface&                  vk                                      = m_context.getDeviceInterface();
+               const VkDevice                                  vkDevice                        = m_context.getDevice();
+               const VkQueue                                   queue                           = m_context.getUniversalQueue();
+               const deUint32                                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
+               SimpleAllocator                                 allocator                       (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
+               de::MovePtr<tcu::TextureLevel>  result                          = readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, m_colorFormat, m_renderSize);
+               compareOk = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
+                                                                                                                         "IntImageCompare",
+                                                                                                                         "Image comparison",
+                                                                                                                         refRenderer.getAccess(),
+                                                                                                                         result->getAccess(),
+                                                                                                                         tcu::UVec4(2, 2, 2, 2),
+                                                                                                                         tcu::IVec3(1, 1, 0),
+                                                                                                                         true,
+                                                                                                                         tcu::COMPARE_LOG_RESULT);
+       }
+       if (compareOk)
+               return tcu::TestStatus::pass("Result image matches reference");
+       else
+               return tcu::TestStatus::fail("Image mismatch");
+ }
+ class PushConstantComputeTest : public vkt::TestCase
+ {
+ public:
+                                                       PushConstantComputeTest         (tcu::TestContext&              testContext,
+                                                                                                                const std::string&             name,
+                                                                                                                const std::string&             description,
+                                                                                                                const PushConstantData pushConstantRange);
+       virtual                                 ~PushConstantComputeTest        (void);
+       virtual void                    initPrograms                            (SourceCollections& sourceCollections) const;
+       virtual TestInstance*   createInstance                          (Context& context) const;
+       
+ private:
+       const PushConstantData  m_pushConstantRange;
+ };
+ class PushConstantComputeTestInstance : public vkt::TestInstance
+ {
+ public:
+                                                       PushConstantComputeTestInstance         (Context&                               context,
+                                                                                                                                const PushConstantData pushConstantRange);
+       virtual                                 ~PushConstantComputeTestInstance        (void);
+       virtual tcu::TestStatus iterate                                                         (void);
+ private:
+       const PushConstantData                  m_pushConstantRange;
+       
+       Move<VkBuffer>                                  m_outBuffer;
+       de::MovePtr<Allocation>                 m_outBufferAlloc;
+       Move<VkDescriptorPool>                  m_descriptorPool;
+       Move<VkDescriptorSetLayout>             m_descriptorSetLayout;
+       Move<VkDescriptorSet>                   m_descriptorSet;
+       
+       Move<VkPipelineLayout>                  m_pipelineLayout;
+       Move<VkPipeline>                                m_computePipelines;
+       
+       Move<VkShaderModule>                    m_computeShaderModule;
+       
+       Move<VkCommandPool>                             m_cmdPool;
+       Move<VkCommandBuffer>                   m_cmdBuffer;
+       Move<VkFence>                                   m_fence;
+ };
+ PushConstantComputeTest::PushConstantComputeTest (tcu::TestContext&                   testContext,
+                                                                                                 const std::string&            name,
+                                                                                                 const std::string&            description,
+                                                                                                 const PushConstantData        pushConstantRange)
+       : vkt::TestCase                 (testContext, name, description)
+       , m_pushConstantRange   (pushConstantRange)
+ {
+ }
+ PushConstantComputeTest::~PushConstantComputeTest (void)
+ {
+ }
+ TestInstance* PushConstantComputeTest::createInstance (Context& context) const
+ {
+       return new PushConstantComputeTestInstance(context, m_pushConstantRange);
+ }
+ void PushConstantComputeTest::initPrograms (SourceCollections& sourceCollections) const
+ {
+       std::ostringstream      computeSrc;
+       
+       computeSrc << "#version 450\n"
+                          << "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
+                          << "layout(std140, set = 0, binding = 0) writeonly buffer Output {\n"
+                          << "  vec4 elements[];\n"
+                          << "} outData;\n"
+                          << "layout(push_constant) uniform Material{\n"
+                          << "  vec4 element;\n"
+                          << "} matInst;\n"
+                          << "void main (void)\n"
+                          << "{\n"
+                          << "  outData.elements[gl_GlobalInvocationID.x] = matInst.element;\n"
+                          << "}\n";
+                   
+       sourceCollections.glslSources.add("compute") << glu::ComputeSource(computeSrc.str());
+ }
+ PushConstantComputeTestInstance::PushConstantComputeTestInstance (Context&                                    context,
+                                                                                                                                 const PushConstantData        pushConstantRange)
+       : vkt::TestInstance             (context)
+       , m_pushConstantRange   (pushConstantRange)
+ {
+       const DeviceInterface&          vk                                      = context.getDeviceInterface();
+       const VkDevice                          vkDevice                        = context.getDevice();
+       const deUint32                          queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
+       SimpleAllocator                         memAlloc                        (vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
+       // Create pipeline layout
+       {
+               // create push constant range
+               VkPushConstantRange     pushConstantRanges;
+               pushConstantRanges.stageFlags   = m_pushConstantRange.range.shaderStage;
+               pushConstantRanges.offset               = m_pushConstantRange.range.offset;
+               pushConstantRanges.size                 = m_pushConstantRange.range.size;
+               
+               // create descriptor set layout
+               m_descriptorSetLayout = DescriptorSetLayoutBuilder().addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT).build(vk, vkDevice);
+               
+               // create descriptor pool
+               m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1u).build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
+               
+               // create uniform buffer
+               const VkDeviceSize                      bufferSize                      = sizeof(tcu::Vec4) * 8;
+               const VkBufferCreateInfo        bufferCreateInfo        =
+               {
+                       VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                                           // VkStructureType              sType;
+                       DE_NULL,                                                                                                        // const void*                  pNext;
+                       bufferSize,                                                                                                     // VkDeviceSize                 size;
+                       VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,                                                     // VkBufferUsageFlags   usage;
+                       0u,                                                                                                                     // VkBufferCreateFlags  flags;
+                       VK_SHARING_MODE_EXCLUSIVE,                                                                      // VkSharingMode                sharingMode;
+                       1u,                                                                                                                     // deUint32                             queueFamilyCount;
+                       &queueFamilyIndex                                                                                       // const deUint32*              pQueueFamilyIndices;
+               };
+               
+               m_outBuffer                     = createBuffer(vk, vkDevice, &bufferCreateInfo);
+               m_outBufferAlloc        = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_outBuffer), MemoryRequirement::HostVisible);
+               VK_CHECK(vk.bindBufferMemory(vkDevice, *m_outBuffer, m_outBufferAlloc->getMemory(), m_outBufferAlloc->getOffset()));
+               
+               // create and update descriptor set
+               const VkDescriptorSetAllocateInfo allocInfo =
+               {
+                       VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,                         // VkStructureType                             sType;
+                       DE_NULL,                                                                                                        // const void*                                 pNext;
+                       *m_descriptorPool,                                                                                      // VkDescriptorPool                            descriptorPool;
+                       1u,                                                                                                                     // uint32_t                                    setLayoutCount;
+                       &(*m_descriptorSetLayout),                                                                      // const VkDescriptorSetLayout*                pSetLayouts;
+               };
+               m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &allocInfo);
+               
+               const VkDescriptorBufferInfo descriptorInfo = makeDescriptorBufferInfo(*m_outBuffer, (VkDeviceSize)0u, bufferSize);
+               
+               DescriptorSetUpdateBuilder()
+                       .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfo)
+                       .update(vk, vkDevice);
+               
+               // create pipeline layout
+               const VkPipelineLayoutCreateInfo        pipelineLayoutParams    =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,          // VkStructureType                              sType;
+                       DE_NULL,                                                                                        // const void*                                  pNext;
+                       0u,                                                                                                     // VkPipelineLayoutCreateFlags  flags;
+                       1u,                                                                                                     // deUint32                                             descriptorSetCount;
+                       &(*m_descriptorSetLayout),                                                      // const VkDescriptorSetLayout* pSetLayouts;
+                       1u,                                                                                                     // deUint32                                             pushConstantRangeCount;
+                       &pushConstantRanges                                                                     // const VkPushConstantRange*   pPushConstantRanges;
+               };
+               
+               m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
+       }
+       
+       // create pipeline
+       {
+               m_computeShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("compute"), 0);
+               
+               const VkPipelineShaderStageCreateInfo   stageCreateInfo =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                                              sType;
+                       DE_NULL,                                                                                                // const void*                                                  pNext;
+                       0u,                                                                                                             // VkPipelineShaderStageCreateFlags             flags;
+                       VK_SHADER_STAGE_COMPUTE_BIT,                                                    // VkShaderStageFlagBits                                stage;
+                       *m_computeShaderModule,                                                                 // VkShaderModule                                               module;
+                       "main",                                                                                                 // const char*                                                  pName;
+                       DE_NULL                                                                                                 // const VkSpecializationInfo*                  pSpecializationInfo;
+               };
+               
+               const VkComputePipelineCreateInfo               createInfo      =
+               {
+                       VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,                 // VkStructureType                             sType;
+                       DE_NULL,                                                                                                // const void*                                 pNext;
+                       0u,                                                                                                             // VkPipelineCreateFlags                       flags;
+                       stageCreateInfo,                                                                                // VkPipelineShaderStageCreateInfo             stage;
+                       *m_pipelineLayout,                                                                              // VkPipelineLayout                            layout;
+                       (VkPipeline)0,                                                                                  // VkPipeline                                  basePipelineHandle;
+                       0u,                                                                                                             // int32_t                                     basePipelineIndex;
+               };
+               m_computePipelines = createComputePipeline(vk, vkDevice, (vk::VkPipelineCache)0u, &createInfo);
+       }
+       
+       // Create command pool
+       {
+               const VkCommandPoolCreateInfo cmdPoolParams =
+               {
+                       VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,             // VkStructureType              sType;
+                       DE_NULL,                                                                                // const void*                  pNext;
+                       VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,                   // VkCmdPoolCreateFlags flags;
+                       queueFamilyIndex                                                                // deUint32                             queueFamilyIndex;
+               };
+               m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
+       }
+       // Create command buffer
+       {
+               const VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
+               {
+                       VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType                      sType;
+                       DE_NULL,                                                                                // const void*                          pNext;
+                       *m_cmdPool,                                                                             // VkCommandPool                        commandPool;
+                       VK_COMMAND_BUFFER_LEVEL_PRIMARY,                                // VkCommandBufferLevel         level;
+                       1u                                                                                              // deUint32                                     bufferCount;
+               };
+               
+               m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdBufferAllocateInfo);
+               const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+               {
+                       VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                                      sType;
+                       DE_NULL,                                                                                // const void*                                          pNext;
+                       0u,                                                                                             // VkCommandBufferUsageFlags            flags;
+                       DE_NULL,                                                                                // VkRenderPass                                         renderPass;
+                       0u,                                                                                             // deUint32                                                     subpass;
+                       DE_NULL,                                                                                // VkFramebuffer                                        framebuffer;
+                       false,                                                                                  // VkBool32                                                     occlusionQueryEnable;
+                       0u,                                                                                             // VkQueryControlFlags                          queryFlags;
+                       0u                                                                                              // VkQueryPipelineStatisticFlags        pipelineStatistics;
+               };
+               
+               VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
+               
+               vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipelines);
+               vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0, 1, &(*m_descriptorSet), 0, DE_NULL);
+               
+               // update push constant
+               tcu::Vec4       value   = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
+               vk.cmdPushConstants(*m_cmdBuffer, *m_pipelineLayout, m_pushConstantRange.range.shaderStage, m_pushConstantRange.range.offset, m_pushConstantRange.range.size, &value);
+               
+               vk.cmdDispatch(*m_cmdBuffer, 8, 1, 1);
+               
+               VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
+       }
+       // Create fence
+       {
+               const VkFenceCreateInfo fenceParams =
+               {
+                       VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,    // VkStructureType              sType;
+                       DE_NULL,                                                                // const void*                  pNext;
+                       0u                                                                              // VkFenceCreateFlags   flags;
+               };
+               m_fence = createFence(vk, vkDevice, &fenceParams);
+       }
+ }
+ PushConstantComputeTestInstance::~PushConstantComputeTestInstance (void)
+ {
+ }
+ tcu::TestStatus PushConstantComputeTestInstance::iterate (void)
+ {
+       const DeviceInterface&          vk                      = m_context.getDeviceInterface();
+       const VkDevice                          vkDevice        = m_context.getDevice();
+       const VkQueue                           queue           = m_context.getUniversalQueue();
+       const VkSubmitInfo                      submitInfo      =
+       {
+               VK_STRUCTURE_TYPE_SUBMIT_INFO,  // VkStructureType                      sType;
+               DE_NULL,                                                // const void*                          pNext;
+               0u,                                                             // deUint32                                     waitSemaphoreCount;
+               DE_NULL,                                                // const VkSemaphore*           pWaitSemaphores;
+               1u,                                                             // deUint32                                     commandBufferCount;
+               &m_cmdBuffer.get(),                             // const VkCommandBuffer*       pCommandBuffers;
+               0u,                                                             // deUint32                                     signalSemaphoreCount;
+               DE_NULL                                                 // const VkSemaphore*           pSignalSemaphores;
+       };
+       VK_CHECK(vk.resetFences(vkDevice, 1, &m_fence.get()));
+       VK_CHECK(vk.queueSubmit(queue, 1, &submitInfo, *m_fence));
+       VK_CHECK(vk.waitForFences(vkDevice, 1, &m_fence.get(), true, ~(0ull) /* infinity*/));
+       // verify result
+       std::vector<tcu::Vec4>  expectValue(8, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
+       if (deMemCmp((void*)(&expectValue[0]), m_outBufferAlloc->getHostPtr(), (size_t)(sizeof(tcu::Vec4) * 8)))
+       {
+               return tcu::TestStatus::fail("Image mismatch");
+       }
+       return tcu::TestStatus::pass("result image matches with reference");
+ }
+ } // anonymous
+ tcu::TestCaseGroup* createPushConstantTests (tcu::TestContext& testCtx)
+ {
+       static const struct
+       {
+               const char*                     name;
+               const char*                     description;
+               deUint32                        count;
+               PushConstantData        range[MAX_RANGE_COUNT];
+               deBool                          hasMultipleUpdates;
+       } graphicsParams[] =
+       {
+               // test range size from minimum valid size to maximum
+               {
+                       "range_size_4",
+                       "test range size is 4 bytes(minimum valid size)",
+                       1u,
+                       { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 4 } , { 0, 4 } } },
+                       false
+               },
+               {
+                       "range_size_16",
+                       "test range size is 16 bytes, and together with a normal uniform",
+                       1u,
+                       { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } } },
+                       false
+               },
+               {
+                       "range_size_128",
+                       "test range size is 128 bytes(maximum valid size)",
+                       1u,
+                       { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 128 }, { 0, 128 } } },
+                       false
+               },
+               // test range count, including all valid shader stage in graphics pipeline, and also multiple shader stages share one single range
+               {
+                       "count_2_shader_VF",
+                       "test range count is 2, use vertex and fragment shaders",
+                       2u,
+                       {
+                               { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
+                               { { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
+                       },
+                       false
+               },
+               {
+                       "count_3shader_VGF",
+                       "test range count is 3, use vertex, geometry and fragment shaders",
+                       3u,
+                       {
+                               { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
+                               { { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
+                               { { VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4 }, { 20, 4 } },
+                       },
+                       false
+               },
+               {
+                       "count_5_shader_VTGF",
+                       "test range count is 5, use vertex, tessellation, geometry and fragment shaders",
+                       5u,
+                       {
+                               { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 0, 16 } },
+                               { { VK_SHADER_STAGE_FRAGMENT_BIT, 16, 4 }, { 16, 4 } },
+                               { { VK_SHADER_STAGE_GEOMETRY_BIT, 20, 4 }, { 20, 4 } },
+                               { { VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, 24, 4 }, { 24, 4 } },
+                               { { VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, 28, 16 }, { 28, 16 } },
+                       },
+                       false
+               },
+               {
+                       "count_1_shader_VF",
+                       "test range count is 1, vertex and fragment shaders share one range",
+                       1u,
+                       { { { VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4 }, { 0, 4 } } },
+                       false
+               },
+               // test data partial update and multiple times update
+               {
+                       "data_update_partial_1",
+                       "test partial update of the values",
+                       1u,
+                       { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 16 }, { 4, 8 } } },
+                       false
+               },
+               {
+                       "data_update_partial_2",
+                       "test partial update of the values",
+                       1u,
+                       { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 40 }, { 24, 16 } } },
+                       false
+               },
+               {
+                       "data_update_multiple",
+                       "test multiple times update of the values",
+                       1u,
+                       { { { VK_SHADER_STAGE_VERTEX_BIT, 0, 4 }, { 0, 4 } } },
+                       true
+               },
+       };
+       
+       static const struct
+       {
+               const char*                     name;
+               const char*                     description;
+               PushConstantData        range;
+       } computeParams[] =
+       {
+               {
+                       "simple_test",
+                       "test compute pipeline",
+                       { { VK_SHADER_STAGE_COMPUTE_BIT, 0, 16 }, { 0, 16 } },
+               },
+       };
+       de::MovePtr<tcu::TestCaseGroup> pushConstantTests       (new tcu::TestCaseGroup(testCtx, "push_constant", "PushConstant tests"));
+       
+       de::MovePtr<tcu::TestCaseGroup> graphicsTests   (new tcu::TestCaseGroup(testCtx, "graphics_pipeline", "graphics pipeline"));
+       for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(graphicsParams); ndx++)
+       {
+               graphicsTests->addChild(new PushConstantGraphicsTest(testCtx, graphicsParams[ndx].name, graphicsParams[ndx].description, graphicsParams[ndx].count, graphicsParams[ndx].range, graphicsParams[ndx].hasMultipleUpdates));
+       }
+       pushConstantTests->addChild(graphicsTests.release());
+       
+       de::MovePtr<tcu::TestCaseGroup> computeTests    (new tcu::TestCaseGroup(testCtx, "compute_pipeline", "compute pipeline"));
+       computeTests->addChild(new PushConstantComputeTest(testCtx, computeParams[0].name, computeParams[0].description, computeParams[0].range));
+       pushConstantTests->addChild(computeTests.release());
+       
+       return pushConstantTests.release();
+ }
+ } // pipeline
+ } // vkt