Add pipeline cache tests
authorRocky Shi <Rocky.Shi@arm.com>
Thu, 10 Mar 2016 21:20:06 +0000 (13:20 -0800)
committerPyry Haulos <phaulos@google.com>
Wed, 23 Mar 2016 21:50:19 +0000 (14:50 -0700)
external/vulkancts/modules/vulkan/pipeline/CMakeLists.txt
external/vulkancts/modules/vulkan/pipeline/vktPipelineCacheTests.cpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/pipeline/vktPipelineCacheTests.hpp [new file with mode: 0644]
external/vulkancts/modules/vulkan/pipeline/vktPipelineTests.cpp

index e1dd8e7..328210f 100644 (file)
@@ -42,6 +42,8 @@ set(DEQP_VK_PIPELINE_SRCS
        vktPipelineVertexUtil.hpp
        vktPipelineEarlyFragmentTests.cpp
        vktPipelineEarlyFragmentTests.hpp
+       vktPipelineCacheTests.cpp
+       vktPipelineCacheTests.hpp
        )
 
 set(DEQP_VK_PIPELINE_LIBS
diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineCacheTests.cpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineCacheTests.cpp
new file mode 100644 (file)
index 0000000..2faf5b3
--- /dev/null
@@ -0,0 +1,1626 @@
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 ARM Ltd.
+ *
+ * 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 Pipeline Cache Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktPipelineCacheTests.hpp"
+#include "vktPipelineClearUtil.hpp"
+#include "vktPipelineImageUtil.hpp"
+#include "vktPipelineVertexUtil.hpp"
+#include "vktTestCase.hpp"
+#include "vktTestCaseUtil.hpp"
+#include "vkImageUtil.hpp"
+#include "vkMemUtil.hpp"
+#include "vkPrograms.hpp"
+#include "vkBuilderUtil.hpp"
+#include "vkQueryUtil.hpp"
+#include "vkRef.hpp"
+#include "vkRefUtil.hpp"
+#include "tcuImageCompare.hpp"
+#include "deUniquePtr.hpp"
+#include "deMemory.h"
+#include "vkTypeUtil.hpp"
+
+#include <sstream>
+#include <vector>
+
+namespace vkt
+{
+namespace pipeline
+{
+
+using namespace vk;
+
+namespace
+{
+enum
+{
+       VK_MAX_SHADER_STAGES = 6,
+};
+
+// helper functions
+
+std::string getShaderFlagStr (const VkShaderStageFlagBits shader,
+                                                         bool                        isDescription)
+{
+       std::ostringstream desc;
+       switch(shader)
+       {
+               case VK_SHADER_STAGE_VERTEX_BIT:
+               {
+                       desc << ((isDescription) ? "vertex stage" : "vertex_stage");
+                       break;
+               }
+               case VK_SHADER_STAGE_FRAGMENT_BIT:
+               {
+                       desc << ((isDescription) ? "fragment stage" : "fragment_stage");
+                       break;
+               }
+               case VK_SHADER_STAGE_GEOMETRY_BIT:
+               {
+                       desc << ((isDescription) ? "geometry stage" : "geometry_stage");
+                       break;
+               }
+               case VK_SHADER_STAGE_COMPUTE_BIT:
+               {
+                       desc << ((isDescription) ? "compute stage" : "compute_stage");
+                       break;
+               }
+               case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
+               {
+                       desc << ((isDescription) ? "tessellation control stage" : "tessellation_control_stage");
+                       break;
+               }
+               case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
+               {
+                       desc << ((isDescription) ? "tessellation evaluation stage" : "tessellation_evaluation_stage");
+                       break;
+               }
+         default:
+               desc << "unknown shader stage!";
+               DE_ASSERT(!"Unknown shader Stage!");
+               break;
+       };
+
+       return desc.str();
+}
+
+// helper classes
+class CacheTestParam
+{
+public:
+                                                               CacheTestParam          (const VkShaderStageFlagBits* shaders,
+                                                                                                                deUint32                     count);
+       virtual                                         ~CacheTestParam         (void);
+       virtual const std::string   generateTestName        (void)          const;
+       virtual const std::string   generateTestDescription (void)          const;
+       VkShaderStageFlagBits       getShaderFlag           (deUint32 ndx)  const   { return m_shaders[ndx]; }
+       deUint32                    getShaderCount          (void)          const   { return (deUint32)m_shaderCount; }
+protected:
+       VkShaderStageFlagBits       m_shaders[VK_MAX_SHADER_STAGES];
+       size_t                      m_shaderCount;
+};
+
+CacheTestParam::CacheTestParam (const VkShaderStageFlagBits* shaders, deUint32 count)
+{
+       DE_ASSERT(count <= VK_MAX_SHADER_STAGES);
+       for (deUint32 ndx = 0; ndx < count; ndx++)
+               m_shaders[ndx] = shaders[ndx];
+       m_shaderCount = count;
+}
+
+CacheTestParam::~CacheTestParam (void)
+{
+}
+
+const std::string CacheTestParam::generateTestName (void) const
+{
+       std::string result(getShaderFlagStr(m_shaders[0], false));
+
+       for(deUint32 ndx = 1; ndx < m_shaderCount; ndx++)
+               result += '_' + getShaderFlagStr(m_shaders[ndx], false) ;
+
+       return result;
+}
+
+const std::string CacheTestParam::generateTestDescription (void) const
+{
+       std::string result("Create pipeline cache with " + getShaderFlagStr(m_shaders[0], true));
+
+       for(deUint32 ndx = 1; ndx < m_shaderCount; ndx++)
+               result += ' ' + getShaderFlagStr(m_shaders[ndx], true);
+
+       return result;
+}
+
+class SimpleGraphicsPipelineBuilder
+{
+public:
+                                        SimpleGraphicsPipelineBuilder  (Context&              context);
+                                        ~SimpleGraphicsPipelineBuilder (void) { }
+       void             bindShaderStage                (VkShaderStageFlagBits stage,
+                                                                                                        const char*           sourceName,
+                                                                                                        const char*           entryName);
+       void             enableTessellationStage        (deUint32              patchControlPoints);
+       Move<VkPipeline> buildPipeline                  (tcu::UVec2            renderSize,
+                                                                                                        VkRenderPass          renderPass,
+                                                                                                        VkPipelineCache       cache);
+protected:
+       Context&                            m_context;
+
+       Move<VkShaderModule>                m_shaderModules[VK_MAX_SHADER_STAGES];
+       deUint32                            m_shaderStageCount;
+       VkPipelineShaderStageCreateInfo     m_shaderStageInfo[VK_MAX_SHADER_STAGES];
+
+       deUint32                            m_patchControlPoints;
+
+       Move<VkPipelineLayout>              m_pipelineLayout;
+       Move<VkPipeline>                    m_graphicsPipelines;
+
+};
+
+SimpleGraphicsPipelineBuilder::SimpleGraphicsPipelineBuilder (Context& context)
+       : m_context(context)
+{
+       m_patchControlPoints = 0;
+       m_shaderStageCount   = 0;
+}
+
+void SimpleGraphicsPipelineBuilder::bindShaderStage (VkShaderStageFlagBits stage,
+                                                                                                        const char*           sourceName,
+                                                                                                        const char*           entryName)
+{
+       const DeviceInterface&  vk        = m_context.getDeviceInterface();
+       const VkDevice          vkDevice  = m_context.getDevice();
+
+       // Create shader module
+       deUint32*               code     = (deUint32*)m_context.getBinaryCollection().get(sourceName).getBinary();
+       deUint32                codeSize  = (deUint32)m_context.getBinaryCollection().get(sourceName).getSize();
+
+       const VkShaderModuleCreateInfo moduleCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,                // VkStructureType             sType;
+               DE_NULL,                                                    // const void*                 pNext;
+               0u,                                                         // VkShaderModuleCreateFlags   flags;
+               codeSize,                                                   // deUintptr                   codeSize;
+               code,                                                       // const deUint32*             pCode;
+       };
+
+       m_shaderModules[m_shaderStageCount] = createShaderModule(vk, vkDevice, &moduleCreateInfo);
+
+       // Prepare shader stage info
+       m_shaderStageInfo[m_shaderStageCount].sType               = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+       m_shaderStageInfo[m_shaderStageCount].pNext               = DE_NULL;
+       m_shaderStageInfo[m_shaderStageCount].flags               = 0u;
+       m_shaderStageInfo[m_shaderStageCount].stage               = stage;
+       m_shaderStageInfo[m_shaderStageCount].module              = *m_shaderModules[m_shaderStageCount];
+       m_shaderStageInfo[m_shaderStageCount].pName               = entryName;
+       m_shaderStageInfo[m_shaderStageCount].pSpecializationInfo = DE_NULL;
+
+       m_shaderStageCount++;
+}
+
+Move<VkPipeline> SimpleGraphicsPipelineBuilder::buildPipeline (tcu::UVec2 renderSize, VkRenderPass renderPass, VkPipelineCache cache)
+{
+       const DeviceInterface&      vk                  = m_context.getDeviceInterface();
+       const VkDevice              vkDevice            = m_context.getDevice();
+
+       // Create pipeline layout
+       {
+               const VkPipelineLayoutCreateInfo pipelineLayoutParams =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,      // VkStructureType                  sType;
+                       DE_NULL,                                            // const void*                      pNext;
+                       0u,                                                 // VkPipelineLayoutCreateFlags      flags;
+                       0u,                                                 // deUint32                         setLayoutCount;
+                       DE_NULL,                                            // const VkDescriptorSetLayout*     pSetLayouts;
+                       0u,                                                 // deUint32                         pushConstantRangeCount;
+                       DE_NULL                                             // const VkPushConstantRange*       pPushConstantRanges;
+               };
+
+               m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
+       }
+
+       // Create pipeline
+       const VkVertexInputBindingDescription vertexInputBindingDescription =
+       {
+               0u,                                 // deUint32                 binding;
+               sizeof(Vertex4RGBA),                // deUint32                 strideInBytes;
+               VK_VERTEX_INPUT_RATE_VERTEX,        // VkVertexInputRate        inputRate;
+       };
+
+       const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
+       {
+               {
+                       0u,                                 // deUint32 location;
+                       0u,                                 // deUint32 binding;
+                       VK_FORMAT_R32G32B32A32_SFLOAT,      // VkFormat format;
+                       0u                                  // deUint32 offsetInBytes;
+               },
+               {
+                       1u,                                 // deUint32 location;
+                       0u,                                 // deUint32 binding;
+                       VK_FORMAT_R32G32B32A32_SFLOAT,      // VkFormat format;
+                       DE_OFFSET_OF(Vertex4RGBA, color),   // 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                                 vertexBindingDescriptionCount;
+               &vertexInputBindingDescription,                                 // const VkVertexInputBindingDescription*   pVertexBindingDescriptions;
+               2u,                                                             // deUint32                                 vertexAttributeDescriptionCount;
+               vertexInputAttributeDescriptions,                               // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
+       };
+
+       const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                          sType;
+               DE_NULL,                                                        // const void*                              pNext;
+               0u,                                                             // VkPipelineInputAssemblyStateCreateFlags  flags;
+               VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,                            // VkPrimitiveTopology                      topology;
+               VK_FALSE,                                                       // VkBool32                                 primitiveRestartEnable;
+       };
+
+       const VkViewport viewport =
+       {
+               0.0f,                       // float    originX;
+               0.0f,                       // float    originY;
+               (float)renderSize.x(),      // float    width;
+               (float)renderSize.y(),      // float    height;
+               0.0f,                       // float    minDepth;
+               1.0f                        // float    maxDepth;
+       };
+       const VkRect2D scissor =
+       {
+               { 0, 0 },                                                       // VkOffset2D  offset;
+               { renderSize.x(), renderSize.y() }                              // VkExtent2D  extent;
+       };
+       const VkPipelineViewportStateCreateInfo viewportStateParams =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,          // VkStructureType                      sType;
+               DE_NULL,                                                        // const void*                          pNext;
+               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;
+               VK_FALSE,                                                       // VkBool32                                 depthClampEnable;
+               VK_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 =
+       {
+               VK_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 |
+               VK_COLOR_COMPONENT_B_BIT |
+               VK_COLOR_COMPONENT_A_BIT                                                    // VkColorComponentFlags    colorWriteMask;
+       };
+
+       const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,   // VkStructureType                              sType;
+               DE_NULL,                                                    // const void*                                  pNext;
+               0u,                                                         // VkPipelineColorBlendStateCreateFlags         flags;
+               VK_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                                        blendConst[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;
+               VK_FALSE,                                                   // VkBool32                                 sampleShadingEnable;
+               0.0f,                                                       // float                                    minSampleShading;
+               DE_NULL,                                                    // const VkSampleMask*                      pSampleMask;
+               VK_FALSE,                                                   // VkBool32                                 alphaToCoverageEnable;
+               VK_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;
+               VK_TRUE,                                                    // VkBool32                                 depthTestEnable;
+               VK_TRUE,                                                    // VkBool32                                 depthWriteEnable;
+               VK_COMPARE_OP_LESS_OR_EQUAL,                                // VkCompareOp                              depthCompareOp;
+               VK_FALSE,                                                   // VkBool32                                 depthBoundsTestEnable;
+               VK_FALSE,                                                   // VkBool32                                 stencilTestEnable;
+               // VkStencilOpState front;
+               {
+                       VK_STENCIL_OP_KEEP,     // VkStencilOp  failOp;
+                       VK_STENCIL_OP_KEEP,     // VkStencilOp  passOp;
+                       VK_STENCIL_OP_KEEP,     // VkStencilOp  depthFailOp;
+                       VK_COMPARE_OP_NEVER,    // VkCompareOp  compareOp;
+                       0u,                     // deUint32     compareMask;
+                       0u,                     // deUint32     writeMask;
+                       0u,                     // deUint32     reference;
+               },
+               // VkStencilOpState back;
+               {
+                       VK_STENCIL_OP_KEEP,     // VkStencilOp  failOp;
+                       VK_STENCIL_OP_KEEP,     // VkStencilOp  passOp;
+                       VK_STENCIL_OP_KEEP,     // VkStencilOp  depthFailOp;
+                       VK_COMPARE_OP_NEVER,    // VkCompareOp  compareOp;
+                       0u,                     // deUint32     compareMask;
+                       0u,                     // deUint32     writeMask;
+                       0u,                     // deUint32     reference;
+               },
+               -1.0f,                                                      // float                                    minDepthBounds;
+               +1.0f,                                                      // float                                    maxDepthBounds;
+       };
+
+       const VkPipelineTessellationStateCreateInfo* pTessCreateInfo = DE_NULL;
+       if (m_patchControlPoints > 0)
+       {
+               const VkPipelineTessellationStateCreateInfo tessStateCreateInfo =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,  // VkStructureType                          sType;
+                       DE_NULL,                                                    // const void*                              pNext;
+                       0u,                                                         // VkPipelineTesselationStateCreateFlags    flags;
+                       m_patchControlPoints,                                       // deUint32                                 patchControlPoints;
+               };
+
+               pTessCreateInfo = &tessStateCreateInfo;
+       }
+
+       const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
+       {
+               VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,    // VkStructureType                                  sType;
+               DE_NULL,                                            // const void*                                      pNext;
+               0u,                                                 // VkPipelineCreateFlags                            flags;
+               m_shaderStageCount,                                 // deUint32                                         stageCount;
+               m_shaderStageInfo,                                  // const VkPipelineShaderStageCreateInfo*           pStages;
+               &vertexInputStateParams,                            // const VkPipelineVertexInputStateCreateInfo*      pVertexInputState;
+               &inputAssemblyStateParams,                          // const VkPipelineInputAssemblyStateCreateInfo*    pInputAssemblyState;
+               pTessCreateInfo,                                    // const VkPipelineTessellationStateCreateInfo*     pTessellationState;
+               &viewportStateParams,                               // const VkPipelineViewportStateCreateInfo*         pViewportState;
+               &rasterStateParams,                                 // const VkPipelineRasterizationStateCreateInfo*    pRasterState;
+               &multisampleStateParams,                            // const VkPipelineMultisampleStateCreateInfo*      pMultisampleState;
+               &depthStencilStateParams,                           // const VkPipelineDepthStencilStateCreateInfo*     pDepthStencilState;
+               &colorBlendStateParams,                             // const VkPipelineColorBlendStateCreateInfo*       pColorBlendState;
+               &dynamicStateParams,                                // const VkPipelineDynamicStateCreateInfo*          pDynamicState;
+               *m_pipelineLayout,                                  // VkPipelineLayout                                 layout;
+               renderPass,                                         // VkRenderPass                                     renderPass;
+               0u,                                                 // deUint32                                         subpass;
+               0u,                                                 // VkPipeline                                       basePipelineHandle;
+               0,                                                  // deInt32                                          basePipelineIndex;
+       };
+
+       return createGraphicsPipeline(vk, vkDevice, cache, &graphicsPipelineParams);
+}
+
+void SimpleGraphicsPipelineBuilder::enableTessellationStage (deUint32 patchControlPoints)
+{
+       m_patchControlPoints = patchControlPoints;
+}
+
+template <class Test>
+vkt::TestCase* newTestCase (tcu::TestContext&     testContext,
+                                                   const CacheTestParam* testParam)
+{
+       return new Test(testContext,
+                                       testParam->generateTestName().c_str(),
+                                       testParam->generateTestDescription().c_str(),
+                                       testParam);
+}
+
+Move<VkBuffer> createBufferAndBindMemory (Context& context, VkDeviceSize size, VkBufferUsageFlags usage, de::MovePtr<Allocation>* pAlloc)
+{
+       const DeviceInterface&  vk               = context.getDeviceInterface();
+       const VkDevice          vkDevice         = context.getDevice();
+       const deUint32          queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+       SimpleAllocator*        memAlloc         = new SimpleAllocator(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
+
+       const VkBufferCreateInfo vertexBufferParams =
+       {
+               VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,       // VkStructureType      sType;
+               DE_NULL,                                    // const void*          pNext;
+               0u,                                         // VkBufferCreateFlags  flags;
+               size,                                       // VkDeviceSize         size;
+               usage,                                      // VkBufferUsageFlags   usage;
+               VK_SHARING_MODE_EXCLUSIVE,                  // VkSharingMode        sharingMode;
+               1u,                                         // deUint32             queueFamilyCount;
+               &queueFamilyIndex                           // const deUint32*      pQueueFamilyIndices;
+       };
+
+       Move<VkBuffer> vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
+
+       DE_ASSERT(pAlloc);
+       *pAlloc = memAlloc->allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
+       VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, (*pAlloc)->getMemory(), (*pAlloc)->getOffset()));
+
+       return vertexBuffer;
+}
+
+Move<VkImage> createImage2DAndBindMemory (Context&                          context,
+                                                                                 VkFormat                          format,
+                                                                                 deUint32                          width,
+                                                                                 deUint32                          height,
+                                                                                 VkImageUsageFlags                 usage,
+                                                                                 VkSampleCountFlagBits             sampleCount,
+                                                                                 de::details::MovePtr<Allocation>* pAlloc)
+{
+       const DeviceInterface&  vk               = context.getDeviceInterface();
+       const VkDevice          vkDevice         = context.getDevice();
+       const deUint32          queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+       SimpleAllocator*        memAlloc         = new SimpleAllocator(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
+
+       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;
+               format,                                                                     // VkFormat             format;
+               { width, height, 1u },                                                      // VkExtent3D           extent;
+               1u,                                                                         // deUint32             mipLevels;
+               1u,                                                                         // deUint32             arraySize;
+               sampleCount,                                                                // deUint32             samples;
+               VK_IMAGE_TILING_OPTIMAL,                                                    // VkImageTiling        tiling;
+               usage,                                                                      // VkImageUsageFlags    usage;
+               VK_SHARING_MODE_EXCLUSIVE,                                                  // VkSharingMode        sharingMode;
+               1u,                                                                         // deUint32             queueFamilyCount;
+               &queueFamilyIndex,                                                          // const deUint32*      pQueueFamilyIndices;
+               VK_IMAGE_LAYOUT_UNDEFINED,                                                  // VkImageLayout        initialLayout;
+       };
+
+       Move<VkImage> image = createImage(vk, vkDevice, &colorImageParams);
+
+       DE_ASSERT(pAlloc);
+       *pAlloc = memAlloc->allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any);
+       VK_CHECK(vk.bindImageMemory(vkDevice, *image, (*pAlloc)->getMemory(), (*pAlloc)->getOffset()));
+
+       return image;
+}
+
+// Test Classes
+class CacheTest : public vkt::TestCase
+{
+public:
+                                                 CacheTest(tcu::TestContext&           testContext,
+                                                                       const std::string&          name,
+                                                                       const std::string&          description,
+                                                                       const CacheTestParam*       param)
+                                                         : vkt::TestCase (testContext, name, description)
+                                                         , m_param (*param)
+                                                         { }
+       virtual               ~CacheTest (void) { }
+protected:
+       const CacheTestParam  m_param;
+};
+
+class CacheTestInstance : public vkt::TestInstance
+{
+public:
+       enum
+       {
+               PIPELINE_CACHE_NDX_NO_CACHE,
+               PIPELINE_CACHE_NDX_CACHED,
+               PIPELINE_CACHE_NDX_COUNT,
+       };
+                                                       CacheTestInstance           (Context&                 context,
+                                                                                                                const CacheTestParam*    param);
+       virtual                 ~CacheTestInstance          (void);
+       virtual tcu::TestStatus iterate                     (void);
+protected:
+       virtual tcu::TestStatus verifyTestResult            (void) = 0;
+       virtual void            prepareCommandBuffer        (void) = 0;
+protected:
+       const CacheTestParam*   m_param;
+
+       Move<VkCommandPool>     m_cmdPool;
+       Move<VkCommandBuffer>   m_cmdBuffer;
+       Move<VkFence>           m_fence;
+       Move<VkPipelineCache>   m_cache;
+};
+
+CacheTestInstance::CacheTestInstance (Context&                 context,
+                                                                         const CacheTestParam*    param)
+       : TestInstance       (context)
+       , m_param            (param)
+{
+       const DeviceInterface&  vk               = m_context.getDeviceInterface();
+       const VkDevice          vkDevice         = m_context.getDevice();
+       const deUint32          queueFamilyIndex = context.getUniversalQueueFamilyIndex();
+
+       // 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 cmdAllocateParams =
+               {
+                       VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType         sType;
+                       DE_NULL,                                        // const void*             pNext;
+                       *m_cmdPool,                                     // VkCommandPool           cmdPool;
+                       VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel    level;
+                       1u,                                             // deUint32                bufferCount;
+               };
+
+               m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdAllocateParams);
+       }
+
+       // 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);
+       }
+
+       // Create the Pipeline Cache
+       {
+               const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,           // VkStructureType             sType;
+                       DE_NULL,                                                // const void*                 pNext;
+                       0u,                                                     // VkPipelineCacheCreateFlags  flags;
+                       0u,                                                     // deUintptr                   initialDataSize;
+                       DE_NULL,                                                // const void*                 pInitialData;
+               };
+
+               m_cache = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
+       }
+}
+
+CacheTestInstance::~CacheTestInstance (void)
+{
+}
+
+tcu::TestStatus CacheTestInstance::iterate (void)
+{
+       const DeviceInterface&  vk       = m_context.getDeviceInterface();
+       const VkDevice          vkDevice = m_context.getDevice();
+       const VkQueue           queue    = m_context.getUniversalQueue();
+
+       prepareCommandBuffer();
+
+       VK_CHECK(vk.resetFences(vkDevice, 1u, &m_fence.get()));
+
+       const VkSubmitInfo          submitInfo =
+       {
+               VK_STRUCTURE_TYPE_SUBMIT_INFO,                      // VkStructureType             sType;
+               DE_NULL,                                            // const void*                 pNext;
+               0u,                                                 // deUint32                    waitSemaphoreCount;
+               DE_NULL,                                            // const VkSemaphore*          pWaitSemaphores;
+               (const VkPipelineStageFlags*)DE_NULL,               // const VkPipelineStageFlags* pWaitDstStageMask;
+               1u,                                                 // deUint32                    commandBufferCount;
+               &m_cmdBuffer.get(),                                 // const VkCommandBuffer*      pCommandBuffers;
+               0u,                                                 // deUint32                    signalSemaphoreCount;
+               DE_NULL,                                            // const VkSemaphore*          pSignalSemaphores;
+       };
+       VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *m_fence));
+
+       VK_CHECK(vk.waitForFences(vkDevice, 1u, &m_fence.get(), true, ~(0ull) /* infinity*/));
+
+       return verifyTestResult();
+}
+
+class GraphicsCacheTest : public CacheTest
+{
+public:
+                                                       GraphicsCacheTest   (tcu::TestContext&      testContext,
+                                                                                                const std::string&     name,
+                                                                                                const std::string&     description,
+                                                                                                const CacheTestParam*  param)
+                                                               : CacheTest (testContext, name, description, param)
+                                                               { }
+       virtual                 ~GraphicsCacheTest  (void) { }
+       virtual void            initPrograms        (SourceCollections&      programCollection) const;
+       virtual TestInstance*   createInstance      (Context&                context) const;
+};
+
+class GraphicsCacheTestInstance : public CacheTestInstance
+{
+public:
+                                                       GraphicsCacheTestInstance   (Context&              context,
+                                                                                                                const CacheTestParam*  param);
+       virtual                 ~GraphicsCacheTestInstance  (void);
+protected:
+                       void            prepareRenderPass           (VkFramebuffer framebuffer, VkPipeline pipeline);
+       virtual void            prepareCommandBuffer        (void);
+       virtual tcu::TestStatus verifyTestResult            (void);
+
+protected:
+       const tcu::UVec2                    m_renderSize;
+       const VkFormat                      m_colorFormat;
+       const VkFormat                      m_depthFormat;
+
+       Move<VkImage>                       m_depthImage;
+       de::MovePtr<Allocation>             m_depthImageAlloc;
+       de::MovePtr<Allocation>             m_colorImageAlloc;
+       Move<VkImageView>                   m_depthAttachmentView;
+
+       Move<VkBuffer>                      m_vertexBuffer;
+       std::vector<Vertex4RGBA>            m_vertices;
+
+       SimpleGraphicsPipelineBuilder       m_pipelineBuilder;
+       Move<VkRenderPass>                  m_renderPass;
+
+       Move<VkImage>                       m_colorImage[PIPELINE_CACHE_NDX_COUNT];
+       Move<VkImageView>                   m_colorAttachmentView[PIPELINE_CACHE_NDX_COUNT];
+       Move<VkFramebuffer>                 m_framebuffer[PIPELINE_CACHE_NDX_COUNT];
+       Move<VkPipeline>                    m_pipeline[PIPELINE_CACHE_NDX_COUNT];
+};
+
+void GraphicsCacheTest::initPrograms (SourceCollections& programCollection) const
+{
+       for (deUint32 shaderNdx = 0; shaderNdx < m_param.getShaderCount(); shaderNdx++)
+       {
+               switch(m_param.getShaderFlag(shaderNdx))
+               {
+                       case VK_SHADER_STAGE_VERTEX_BIT:
+                               programCollection.glslSources.add("color_vert") << glu::VertexSource(
+                                       "#version 310 es\n"
+                                       "layout(location = 0) in vec4 position;\n"
+                                       "layout(location = 1) in vec4 color;\n"
+                                       "layout(location = 0) out highp vec4 vtxColor;\n"
+                                       "void main (void)\n"
+                                       "{\n"
+                                       "  gl_Position = position;\n"
+                                       "  vtxColor = color;\n"
+                                       "}\n");
+                               break;
+
+                       case VK_SHADER_STAGE_FRAGMENT_BIT:
+                               programCollection.glslSources.add("color_frag") << glu::FragmentSource(
+                                       "#version 310 es\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");
+                               break;
+
+                       case VK_SHADER_STAGE_GEOMETRY_BIT:
+                               programCollection.glslSources.add("dummy_geo") << glu::GeometrySource(
+                                       "#version 450 \n"
+                                       "layout (triangles) in;\n"
+                                       "layout (triangle_strip, max_vertices = 3) out;\n"
+                                       "void main (void)\n"
+                                       "{\n"
+                                       "  for(int ndx=0; ndx<3; ndx++)\n"
+                                       "  {\n"
+                                       "    gl_Position = gl_in[ndx].gl_Position;\n"
+                                       "    EmitVertex();\n"
+                                       "  }\n"
+                                       "  EndPrimitive();\n"
+                                       "}\n");
+                               break;
+
+                       case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
+                               programCollection.glslSources.add("basic_tcs") << glu::TessellationControlSource(
+                                       "#version 450 \n"
+                                       "layout(vertices = 3) out;\n"
+                                       "in highp vec4 color[];\n"
+                                       "out highp vec4 vtxColor[];\n"
+                                       "void main()\n"
+                                       "{\n"
+                                       "  gl_TessLevelOuter[0] = 4.0;\n"
+                                       "  gl_TessLevelOuter[1] = 4.0;\n"
+                                       "  gl_TessLevelOuter[2] = 4.0;\n"
+                                       "  gl_TessLevelInner[0] = 4.0;\n"
+                                       "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+                                       "  vtxColor[gl_InvocationID] = color[gl_InvocationID];\n"
+                                       "}\n");
+                               break;
+
+                       case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
+                               programCollection.glslSources.add("basic_tes") << glu::TessellationEvaluationSource(
+                                       "#version 450 \n"
+                                       "layout(triangles, fractional_even_spacing, ccw) in;\n"
+                                       "in highp vec4 colors[];\n"
+                                       "out highp vec4 vtxColor;\n"
+                                       "void main() \n"
+                                       "{\n"
+                                       "  float u = gl_TessCoord.x;\n"
+                                       "  float v = gl_TessCoord.y;\n"
+                                       "  float w = gl_TessCoord.z;\n"
+                                       "  vec4 pos = vec4(0);\n"
+                                       "  vec4 color = vec4(0);\n"
+                                       "  pos.xyz += u * gl_in[0].gl_Position.xyz;\n"
+                                       "  color.xyz += u * colors[0].xyz;\n"
+                                       "  pos.xyz += v * gl_in[1].gl_Position.xyz;\n"
+                                       "  color.xyz += v * colors[1].xyz;\n"
+                                       "  pos.xyz += w * gl_in[2].gl_Position.xyz;\n"
+                                       "  color.xyz += w * colors[2].xyz;\n"
+                                       "  pos.w = 1.0;\n"
+                                       "  color.w = 1.0;\n"
+                                       "  gl_Position = pos;\n"
+                                       "  vtxColor = color;\n"
+                                       "}\n");
+                               break;
+
+                       default:
+                               DE_ASSERT(!"Unknown Shader Stage!");
+                               break;
+               };
+       }
+}
+
+TestInstance* GraphicsCacheTest::createInstance (Context& context) const
+{
+       return new GraphicsCacheTestInstance(context, &m_param);
+}
+
+GraphicsCacheTestInstance::GraphicsCacheTestInstance (Context&              context,
+                                                                                                         const CacheTestParam* param)
+       : CacheTestInstance (context,param)
+       , m_renderSize      (32u, 32u)
+       , m_colorFormat     (VK_FORMAT_R8G8B8A8_UNORM)
+       , m_depthFormat     (VK_FORMAT_D24_UNORM_S8_UINT)
+       , m_pipelineBuilder (context)
+{
+       const DeviceInterface&  vk               = m_context.getDeviceInterface();
+       const VkDevice          vkDevice         = m_context.getDevice();
+
+       // Create vertex buffer
+       {
+               de::MovePtr<Allocation>     bufferAlloc;
+               m_vertexBuffer = createBufferAndBindMemory(m_context, 1024u, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &bufferAlloc);
+
+               m_vertices          = createOverlappingQuads();
+               // Load vertices into vertex buffer
+               deMemcpy(bufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
+               flushMappedMemoryRange(vk, vkDevice, bufferAlloc->getMemory(), bufferAlloc->getOffset(), 1024u);
+       }
+
+       // 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_UNDEFINED,                          // VkImageLayout                   initialLayout;
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,           // VkImageLayout                   finalLayout;
+               };
+
+               const VkAttachmentDescription depthAttachmentDescription =
+               {
+                       0u,                                                 // VkAttachmentDescriptionFlags flags;
+                       m_depthFormat,                                      // VkFormat                     format;
+                       VK_SAMPLE_COUNT_1_BIT,                              // VkSampleCountFlagBits        samples;
+                       VK_ATTACHMENT_LOAD_OP_CLEAR,                        // VkAttachmentLoadOp           loadOp;
+                       VK_ATTACHMENT_STORE_OP_DONT_CARE,                   // VkAttachmentStoreOp          storeOp;
+                       VK_ATTACHMENT_LOAD_OP_DONT_CARE,                    // VkAttachmentLoadOp           stencilLoadOp;
+                       VK_ATTACHMENT_STORE_OP_DONT_CARE,                   // VkAttachmentStoreOp          stencilStoreOp;
+                       VK_IMAGE_LAYOUT_UNDEFINED,                          // VkImageLayout                initialLayout;
+                       VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,   // VkImageLayout                finalLayout;
+               };
+
+               const VkAttachmentDescription attachments[2] =
+               {
+                       colorAttachmentDescription,
+                       depthAttachmentDescription
+               };
+
+               const VkAttachmentReference colorAttachmentReference =
+               {
+                       0u,                                                 // deUint32         attachment;
+                       VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL            // VkImageLayout    layout;
+               };
+
+               const VkAttachmentReference depthAttachmentReference =
+               {
+                       1u,                                                 // deUint32         attachment;
+                       VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL    // 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;
+                       2u,                                                 // 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);
+       }
+
+       const VkComponentMapping    ComponentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
+       // Create color image
+       {
+               m_colorImage[PIPELINE_CACHE_NDX_NO_CACHE] = createImage2DAndBindMemory(m_context,
+                                                                                                                                                          m_colorFormat,
+                                                                                                                                                          m_renderSize.x(),
+                                                                                                                                                          m_renderSize.y(),
+                                                                                                                                                          VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
+                                                                                                                                                          VK_SAMPLE_COUNT_1_BIT,
+                                                                                                                                                          &m_colorImageAlloc);
+               m_colorImage[PIPELINE_CACHE_NDX_CACHED]   = createImage2DAndBindMemory(m_context,
+                                                                                                                                                          m_colorFormat,
+                                                                                                                                                          m_renderSize.x(),
+                                                                                                                                                          m_renderSize.y(),
+                                                                                                                                                          VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
+                                                                                                                                                          VK_SAMPLE_COUNT_1_BIT,
+                                                                                                                                                          &m_colorImageAlloc);
+       }
+
+       // Create depth image
+       {
+               m_depthImage = createImage2DAndBindMemory(m_context,
+                                                                                                 m_depthFormat,
+                                                                                                 m_renderSize.x(),
+                                                                                                 m_renderSize.y(),
+                                                                                                 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
+                                                                                                 VK_SAMPLE_COUNT_1_BIT,
+                                                                                                 &m_depthImageAlloc);
+       }
+
+       // Create color attachment view
+       {
+               VkImageViewCreateInfo colorAttachmentViewParams =
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType          sType;
+                       DE_NULL,                                        // const void*              pNext;
+                       0u,                                             // VkImageViewCreateFlags   flags;
+                       *m_colorImage[PIPELINE_CACHE_NDX_NO_CACHE],     // VkImage                  image;
+                       VK_IMAGE_VIEW_TYPE_2D,                          // VkImageViewType          viewType;
+                       m_colorFormat,                                  // VkFormat                 format;
+                       ComponentMappingRGBA,                           // VkComponentMapping       components;
+                       { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },  // VkImageSubresourceRange  subresourceRange;
+               };
+
+               m_colorAttachmentView[PIPELINE_CACHE_NDX_NO_CACHE] = createImageView(vk, vkDevice, &colorAttachmentViewParams);
+
+               colorAttachmentViewParams.image = *m_colorImage[PIPELINE_CACHE_NDX_CACHED];
+               m_colorAttachmentView[PIPELINE_CACHE_NDX_CACHED] = createImageView(vk, vkDevice, &colorAttachmentViewParams);
+       }
+
+       // Create depth attachment view
+       {
+               const VkImageViewCreateInfo depthAttachmentViewParams =
+               {
+                       VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType          sType;
+                       DE_NULL,                                        // const void*              pNext;
+                       0u,                                             // VkImageViewCreateFlags   flags;
+                       *m_depthImage,                                  // VkImage                  image;
+                       VK_IMAGE_VIEW_TYPE_2D,                          // VkImageViewType          viewType;
+                       m_depthFormat,                                  // VkFormat                 format;
+                       ComponentMappingRGBA,                           // VkComponentMapping       components;
+                       { VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u },  // VkImageSubresourceRange  subresourceRange;
+               };
+
+               m_depthAttachmentView = createImageView(vk, vkDevice, &depthAttachmentViewParams);
+       }
+
+       // Create framebuffer
+       {
+               VkImageView attachmentBindInfos[2] =
+               {
+                       *m_colorAttachmentView[PIPELINE_CACHE_NDX_NO_CACHE],
+                       *m_depthAttachmentView,
+               };
+
+               const VkFramebufferCreateInfo framebufferParams =
+               {
+                       VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,          // VkStructureType              sType;
+                       DE_NULL,                                            // const void*                  pNext;
+                       0u,                                                 // VkFramebufferCreateFlags     flags;
+                       *m_renderPass,                                      // VkRenderPass                 renderPass;
+                       2u,                                                 // deUint32                     attachmentCount;
+                       attachmentBindInfos,                                // const VkImageView*           pAttachments;
+                       (deUint32)m_renderSize.x(),                         // deUint32                     width;
+                       (deUint32)m_renderSize.y(),                         // deUint32                     height;
+                       1u,                                                 // deUint32                     layers;
+               };
+
+               m_framebuffer[PIPELINE_CACHE_NDX_NO_CACHE] = createFramebuffer(vk, vkDevice, &framebufferParams);
+
+               attachmentBindInfos[0] = *m_colorAttachmentView[PIPELINE_CACHE_NDX_CACHED];
+               m_framebuffer[PIPELINE_CACHE_NDX_CACHED] = createFramebuffer(vk, vkDevice, &framebufferParams);
+       }
+
+       // Bind shader stages
+       VkPhysicalDeviceFeatures  features = m_context.getDeviceFeatures();
+       for (deUint32 shaderNdx = 0; shaderNdx < m_param->getShaderCount(); shaderNdx++)
+       {
+               switch(m_param->getShaderFlag(shaderNdx))
+               {
+                       case VK_SHADER_STAGE_VERTEX_BIT:
+                               m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_VERTEX_BIT, "color_vert", "main");
+                               break;
+                       case VK_SHADER_STAGE_FRAGMENT_BIT:
+                               m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_FRAGMENT_BIT, "color_frag", "main");
+                               break;
+                       case VK_SHADER_STAGE_GEOMETRY_BIT:
+                               if (features.geometryShader == VK_FALSE)
+                               {
+                                       TCU_THROW(NotSupportedError, "Geometry Shader Not Supported");
+                               }
+                               else
+                               {
+                                       m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_GEOMETRY_BIT, "dummy_geo", "main");
+                               }
+                               break;
+                       case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
+                               if (features.tessellationShader == VK_FALSE)
+                               {
+                                       TCU_THROW(NotSupportedError, "Tessellation Not Supported");
+                               }
+                               else
+                               {
+                                       m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "basic_tcs", "main");
+                               }
+                               break;
+                       case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
+                               if (features.tessellationShader == VK_FALSE)
+                               {
+                                       TCU_THROW(NotSupportedError, "Tessellation Not Supported");
+                               }
+                               else
+                               {
+                                       m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "basic_tes", "main");
+                               }
+                               break;
+                       default:
+                               DE_ASSERT(!"Unknown Shader Stage!");
+                               break;
+               };
+       }
+
+       m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE] = m_pipelineBuilder.buildPipeline(m_renderSize, *m_renderPass, *m_cache);
+       m_pipeline[PIPELINE_CACHE_NDX_CACHED]   = m_pipelineBuilder.buildPipeline(m_renderSize, *m_renderPass, *m_cache);
+}
+
+GraphicsCacheTestInstance::~GraphicsCacheTestInstance (void)
+{
+}
+
+void GraphicsCacheTestInstance::prepareRenderPass (VkFramebuffer framebuffer, VkPipeline pipeline)
+{
+       const DeviceInterface&  vk               = m_context.getDeviceInterface();
+
+       const VkClearValue attachmentClearValues[2] =
+       {
+               defaultClearValue(m_colorFormat),
+               defaultClearValue(m_depthFormat),
+       };
+
+       const VkRenderPassBeginInfo renderPassBeginInfo =
+       {
+               VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,               // VkStructureType      sType;
+               DE_NULL,                                                // const void*          pNext;
+               *m_renderPass,                                          // VkRenderPass         renderPass;
+               framebuffer,                                            // VkFramebuffer        framebuffer;
+               { { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } },   // VkRect2D             renderArea;
+               2u,                                                     // deUint32             clearValueCount;
+               attachmentClearValues                                   // const VkClearValue*  pClearValues;
+       };
+
+       vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+       vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
+       VkDeviceSize offsets = 0u;
+       vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &offsets);
+       vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1u, 0u, 0u);
+
+       vk.cmdEndRenderPass(*m_cmdBuffer);
+}
+
+void GraphicsCacheTestInstance::prepareCommandBuffer (void)
+{
+       const DeviceInterface&  vk               = m_context.getDeviceInterface();
+
+       const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+       {
+               VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                  sType;
+               DE_NULL,                                        // const void*                      pNext;
+               0u,                                             // VkCommandBufferUsageFlags        flags;
+               (const VkCommandBufferInheritanceInfo*)DE_NULL,
+       };
+
+       VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
+
+       prepareRenderPass(*m_framebuffer[PIPELINE_CACHE_NDX_NO_CACHE], *m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE]);
+
+       prepareRenderPass(*m_framebuffer[PIPELINE_CACHE_NDX_CACHED], *m_pipeline[PIPELINE_CACHE_NDX_CACHED]);
+
+       VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
+}
+
+tcu::TestStatus GraphicsCacheTestInstance::verifyTestResult (void)
+{
+       const DeviceInterface&  vk               = m_context.getDeviceInterface();
+       const VkDevice          vkDevice         = m_context.getDevice();
+       const deUint32          queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
+       SimpleAllocator*        memAlloc         = new SimpleAllocator(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
+
+       const VkQueue                   queue               = m_context.getUniversalQueue();
+       de::MovePtr<tcu::TextureLevel>  resultNoCache       = readColorAttachment(vk,
+                                                                                                                                                         vkDevice,
+                                                                                                                                                         queue,
+                                                                                                                                                         queueFamilyIndex,
+                                                                                                                                                         *memAlloc,
+                                                                                                                                                         *m_colorImage[PIPELINE_CACHE_NDX_NO_CACHE],
+                                                                                                                                                         m_colorFormat,
+                                                                                                                                                         m_renderSize);
+       de::MovePtr<tcu::TextureLevel>  resultCache         = readColorAttachment(vk,
+                                                                                                                                                         vkDevice,
+                                                                                                                                                         queue,
+                                                                                                                                                         queueFamilyIndex,
+                                                                                                                                                         *memAlloc,
+                                                                                                                                                         *m_colorImage[PIPELINE_CACHE_NDX_CACHED],
+                                                                                                                                                         m_colorFormat,
+                                                                                                                                                         m_renderSize);
+
+       bool compareOk = tcu::intThresholdCompare(m_context.getTestContext().getLog(),
+                                                                                         "IntImageCompare",
+                                                                                         "Image comparison",
+                                                                                         resultNoCache->getAccess(),
+                                                                                         resultCache->getAccess(),
+                                                                                         tcu::UVec4(1, 1, 1, 1),
+                                                                                         tcu::COMPARE_LOG_RESULT);
+
+       if (compareOk)
+               return tcu::TestStatus::pass("Render images w/o cached pipeline match.");
+       else
+               return tcu::TestStatus::fail("Render Images mismatch.");
+}
+
+class ComputeCacheTest : public CacheTest
+{
+public:
+                                                       ComputeCacheTest    (tcu::TestContext&      testContext,
+                                                                                                const std::string&     name,
+                                                                                                const std::string&     description,
+                                                                                                const CacheTestParam*  param)
+                                                               : CacheTest (testContext, name, description, param)
+                                                               { }
+       virtual                 ~ComputeCacheTest   (void) { }
+       virtual void            initPrograms        (SourceCollections&      programCollection) const;
+       virtual TestInstance*   createInstance      (Context&                context) const;
+};
+
+class ComputeCacheTestInstance : public CacheTestInstance
+{
+public:
+                                                       ComputeCacheTestInstance    (Context&               context,
+                                                                                                                const CacheTestParam*  param);
+       virtual                 ~ComputeCacheTestInstance   (void);
+       virtual void            prepareCommandBuffer        (void);
+protected:
+       virtual tcu::TestStatus verifyTestResult            (void);
+                       void            buildBuffers                (void);
+                       void            buildDescriptorSets         (deUint32 ndx);
+                       void            buildShader                 (void);
+                       void            buildPipeline               (deUint32 ndx);
+protected:
+       Move<VkBuffer>              m_inputBuf;
+       Move<VkShaderModule>        m_computeShaderModule;
+
+       Move<VkBuffer>              m_outputBuf[PIPELINE_CACHE_NDX_COUNT];
+       de::MovePtr<Allocation>     m_outputBufferAlloc[PIPELINE_CACHE_NDX_COUNT];
+
+       Move<VkDescriptorPool>      m_descriptorPool[PIPELINE_CACHE_NDX_COUNT];
+       Move<VkDescriptorSetLayout> m_descriptorSetLayout[PIPELINE_CACHE_NDX_COUNT];
+       Move<VkDescriptorSet>       m_descriptorSet[PIPELINE_CACHE_NDX_COUNT];
+
+       Move<VkPipelineLayout>      m_pipelineLayout[PIPELINE_CACHE_NDX_COUNT];
+       Move<VkPipeline>            m_pipeline[PIPELINE_CACHE_NDX_COUNT];
+};
+
+void ComputeCacheTest::initPrograms (SourceCollections& programCollection) const
+{
+       programCollection.glslSources.add("basic_compute") << glu::ComputeSource(
+               "#version 310 es\n"
+               "layout(local_size_x = 128) in;\n"
+               "layout(std430) buffer;\n"
+               "layout(binding = 0) readonly buffer Input0\n"
+               "{\n"
+               "  vec4 elements[];\n"
+               "} input_data0;\n"
+               "layout(binding = 1) writeonly buffer Output\n"
+               "{\n"
+               "  vec4 elements[];\n"
+               "} output_data;\n"
+               "void main()\n"
+               "{\n"
+               "  uint ident = gl_GlobalInvocationID.x;\n"
+               "  output_data.elements[ident] = input_data0.elements[ident] * input_data0.elements[ident];\n"
+               "}");
+}
+
+TestInstance* ComputeCacheTest::createInstance (Context& context) const
+{
+       return new ComputeCacheTestInstance(context, &m_param);
+}
+
+void ComputeCacheTestInstance::buildBuffers (void)
+{
+       const DeviceInterface&  vk               = m_context.getDeviceInterface();
+       const VkDevice          vkDevice         = m_context.getDevice();
+
+       // Create buffer object, allocate storage, and generate input data
+       const VkDeviceSize          size                = sizeof(tcu::Vec4) * 128u;
+       de::MovePtr<Allocation>     bufferAlloc;
+       m_inputBuf = createBufferAndBindMemory(m_context, size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, &bufferAlloc);
+
+       // Initialize input buffer
+       tcu::Vec4* pVec = reinterpret_cast<tcu::Vec4*>(bufferAlloc->getHostPtr());
+       for (deUint32 ndx = 0u; ndx < 128u; ndx++)
+       {
+               for (deUint32 component = 0u; component < 4u; component++)
+                       pVec[ndx][component]= (float)(ndx * (component + 1u));
+       }
+       flushMappedMemoryRange(vk, vkDevice, bufferAlloc->getMemory(), bufferAlloc->getOffset(), size);
+
+       // Clear the output buffer
+       for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
+       {
+               m_outputBuf[ndx] = createBufferAndBindMemory(m_context, size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, &m_outputBufferAlloc[ndx]);
+
+               pVec = reinterpret_cast<tcu::Vec4*>(m_outputBufferAlloc[ndx]->getHostPtr());
+               memset(pVec, 0u, size);
+               flushMappedMemoryRange(vk, vkDevice, m_outputBufferAlloc[ndx]->getMemory(), m_outputBufferAlloc[ndx]->getOffset(), size);
+       }
+}
+
+void ComputeCacheTestInstance::buildDescriptorSets (deUint32 ndx)
+{
+       const DeviceInterface&  vk               = m_context.getDeviceInterface();
+       const VkDevice          vkDevice         = m_context.getDevice();
+
+       // Create descriptor set layout
+       DescriptorSetLayoutBuilder descLayoutBuilder;
+
+       for (deUint32 bindingNdx = 0u; bindingNdx < 2u; bindingNdx++)
+               descLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
+
+       m_descriptorSetLayout[ndx] = descLayoutBuilder.build(vk, vkDevice);
+
+       std::vector<VkDescriptorBufferInfo>        descriptorInfos;
+       descriptorInfos.push_back(makeDescriptorBufferInfo(*m_inputBuf, 0u, sizeof(tcu::Vec4) * 128u));
+       descriptorInfos.push_back(makeDescriptorBufferInfo(*m_outputBuf[ndx], 0u, sizeof(tcu::Vec4) * 128u));
+
+       // Create descriptor pool
+       m_descriptorPool[ndx] = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2u).build(vk,
+                                                                                                                                                                                                                vkDevice,
+                                                                                                                                                                                                                VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
+                                                                                                                                                                                                                1u);
+
+       // Create descriptor set
+       const VkDescriptorSetAllocateInfo descriptorSetAllocInfo =
+       {
+               VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,     // VkStructureType                 sType;
+               DE_NULL,                                            // const void*                     pNext;
+               *m_descriptorPool[ndx],                             // VkDescriptorPool                descriptorPool;
+               1u,                                                 // deUint32                        setLayoutCount;
+               &m_descriptorSetLayout[ndx].get(),                  // const VkDescriptorSetLayout*    pSetLayouts;
+       };
+       m_descriptorSet[ndx] = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocInfo);
+
+       DescriptorSetUpdateBuilder  builder;
+       for (deUint32 descriptorNdx = 0u; descriptorNdx < 2u; descriptorNdx++)
+       {
+               builder.writeSingle(*m_descriptorSet[ndx],
+                                                       DescriptorSetUpdateBuilder::Location::binding(descriptorNdx),
+                                                       VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+                                                       &descriptorInfos[descriptorNdx]);
+       }
+       builder.update(vk, vkDevice);
+}
+
+void ComputeCacheTestInstance::buildShader (void)
+{
+       const DeviceInterface&  vk               = m_context.getDeviceInterface();
+       const VkDevice          vkDevice         = m_context.getDevice();
+
+       // Create compute shader
+       VkShaderModuleCreateInfo shaderModuleCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,                                    // VkStructureType             sType;
+               DE_NULL,                                                                        // const void*                 pNext;
+               0u,                                                                             // VkShaderModuleCreateFlags   flags;
+               m_context.getBinaryCollection().get("basic_compute").getSize(),                 // deUintptr                   codeSize;
+               (deUint32*)m_context.getBinaryCollection().get("basic_compute").getBinary(),    // const deUint32*             pCode;
+       };
+       m_computeShaderModule = createShaderModule(vk, vkDevice, &shaderModuleCreateInfo);
+}
+
+void ComputeCacheTestInstance::buildPipeline (deUint32 ndx)
+{
+       const DeviceInterface&  vk               = m_context.getDeviceInterface();
+       const VkDevice          vkDevice         = m_context.getDevice();
+
+       // Create compute pipeline layout
+       const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,  // VkStructureType                 sType;
+               DE_NULL,                                        // const void*                     pNext;
+               0u,                                             // VkPipelineLayoutCreateFlags     flags;
+               1u,                                             // deUint32                        setLayoutCount;
+               &m_descriptorSetLayout[ndx].get(),              // const VkDescriptorSetLayout*    pSetLayouts;
+               0u,                                             // deUint32                        pushConstantRangeCount;
+               DE_NULL,                                        // const VkPushConstantRange*      pPushConstantRanges;
+       };
+
+       m_pipelineLayout[ndx] = createPipelineLayout(vk, vkDevice, &pipelineLayoutCreateInfo);
+
+       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 pipelineCreateInfo =
+       {
+               VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,      // VkStructureType                 sType;
+               DE_NULL,                                             // const void*                     pNext;
+               0u,                                                  // VkPipelineCreateFlags           flags;
+               stageCreateInfo,                                     // VkPipelineShaderStageCreateInfo stage;
+               *m_pipelineLayout[ndx],                              // VkPipelineLayout                layout;
+               (VkPipeline)0,                                       // VkPipeline                      basePipelineHandle;
+               0u,                                                  // deInt32                         basePipelineIndex;
+       };
+
+       m_pipeline[ndx] = createComputePipeline(vk, vkDevice, *m_cache, &pipelineCreateInfo);
+}
+
+ComputeCacheTestInstance::ComputeCacheTestInstance (Context&              context,
+                                                                                                   const CacheTestParam*  param)
+       : CacheTestInstance (context, param)
+{
+       buildBuffers();
+
+       buildDescriptorSets(PIPELINE_CACHE_NDX_NO_CACHE);
+
+       buildDescriptorSets(PIPELINE_CACHE_NDX_CACHED);
+
+       buildShader();
+
+       buildPipeline(PIPELINE_CACHE_NDX_NO_CACHE);
+
+       buildPipeline(PIPELINE_CACHE_NDX_CACHED);
+}
+
+ComputeCacheTestInstance::~ComputeCacheTestInstance (void)
+{
+}
+
+void ComputeCacheTestInstance::prepareCommandBuffer (void)
+{
+       const DeviceInterface&  vk               = m_context.getDeviceInterface();
+
+       const VkCommandBufferBeginInfo cmdBufferBeginInfo =
+       {
+               VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                  sType;
+               DE_NULL,                                        // const void*                      pNext;
+               0u,                                             // VkCommandBufferUsageFlags        flags;
+               (const VkCommandBufferInheritanceInfo*)DE_NULL,
+       };
+
+       VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
+
+       for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
+       {
+               vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline[ndx]);
+               vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout[ndx], 0u, 1u, &m_descriptorSet[ndx].get(), 0u, DE_NULL);
+               vk.cmdDispatch(*m_cmdBuffer, 128u, 1u, 1u);
+       }
+
+       VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
+}
+
+tcu::TestStatus ComputeCacheTestInstance::verifyTestResult (void)
+{
+       const DeviceInterface&  vk               = m_context.getDeviceInterface();
+       const VkDevice          vkDevice         = m_context.getDevice();
+
+       // Read the content of output buffers
+       invalidateMappedMemoryRange(vk,
+                                                               vkDevice,
+                                                               m_outputBufferAlloc[PIPELINE_CACHE_NDX_NO_CACHE]->getMemory(),
+                                                               m_outputBufferAlloc[PIPELINE_CACHE_NDX_NO_CACHE]->getOffset(),
+                                                               sizeof(tcu::Vec4) * 128u);
+
+       invalidateMappedMemoryRange(vk,
+                                                               vkDevice,
+                                                               m_outputBufferAlloc[PIPELINE_CACHE_NDX_CACHED]->getMemory(),
+                                                               m_outputBufferAlloc[PIPELINE_CACHE_NDX_CACHED]->getOffset(),
+                                                               sizeof(tcu::Vec4) * 128u);
+       // Compare the content
+       deUint8* bufNoCache = reinterpret_cast<deUint8*>(m_outputBufferAlloc[PIPELINE_CACHE_NDX_NO_CACHE]->getHostPtr());
+       deUint8* bufCached  = reinterpret_cast<deUint8*>(m_outputBufferAlloc[PIPELINE_CACHE_NDX_CACHED]->getHostPtr());
+       for (deUint32 ndx = 0u; ndx < sizeof(tcu::Vec4) * 128u; ndx++)
+       {
+               if (bufNoCache[ndx] != bufCached[ndx])
+               {
+                       return tcu::TestStatus::fail("Output buffers w/o cached pipeline mismatch.");
+               }
+       }
+
+       return tcu::TestStatus::pass("Output buffers w/o cached pipeline match.");
+}
+
+class MergeCacheTest : public GraphicsCacheTest
+{
+public:
+                                                       MergeCacheTest      (tcu::TestContext&      testContext,
+                                                                                                const std::string&     name,
+                                                                                                const std::string&     description,
+                                                                                                const CacheTestParam*  param)
+                                                               : GraphicsCacheTest (testContext, name, description, param)
+                                                               { }
+       virtual                 ~MergeCacheTest     (void) { }
+       virtual TestInstance*   createInstance      (Context&               context) const;
+};
+
+class MergeCacheTestInstance : public GraphicsCacheTestInstance
+{
+public:
+                                                       MergeCacheTestInstance  (Context&              context,
+                                                                                                        const CacheTestParam*  param);
+       virtual                 ~MergeCacheTestInstance (void);
+protected:
+protected:
+       Move<VkPipelineCache>   m_cacheGetData;
+       Move<VkPipelineCache>   m_cacheEmpty;
+       Move<VkPipelineCache>   m_cacheMerged;
+       deUint8*                m_data;
+};
+
+TestInstance* MergeCacheTest::createInstance (Context& context) const
+{
+       return new MergeCacheTestInstance(context, &m_param);
+}
+
+MergeCacheTestInstance::MergeCacheTestInstance (Context& context, const CacheTestParam* param)
+       : GraphicsCacheTestInstance (context, param)
+       , m_data                    (DE_NULL)
+{
+       const DeviceInterface&  vk               = m_context.getDeviceInterface();
+       const VkDevice          vkDevice         = m_context.getDevice();
+
+       // Create more pipeline caches
+       {
+               // Create a empty cache as one of source cache
+               VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
+               {
+                       VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,           // VkStructureType             sType;
+                       DE_NULL,                                                // const void*                 pNext;
+                       0u,                                                     // VkPipelineCacheCreateFlags  flags;
+                       0u,                                                     // deUintptr                   initialDataSize;
+                       DE_NULL,                                                // const void*                 pInitialData;
+               };
+               m_cacheEmpty = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
+
+               // Create a empty cache for merge destination cache
+               m_cacheMerged = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
+
+               // Create a cache with init data from m_cache
+               size_t  dataSize = 0u;
+               VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, DE_NULL));
+
+               m_data = new deUint8[dataSize];
+               DE_ASSERT(m_data);
+               VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, (void*)m_data));
+
+               pipelineCacheCreateInfo.initialDataSize = dataSize;
+               pipelineCacheCreateInfo.pInitialData = m_data;
+               m_cacheGetData = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
+       }
+
+       // Merge the caches
+       const VkPipelineCache sourceCaches[] =
+       {
+               *m_cacheEmpty,
+               *m_cacheGetData,
+       };
+       VK_CHECK(vk.mergePipelineCaches(vkDevice, *m_cacheMerged, 2u, sourceCaches));
+
+       // Create pipeline from merged cache
+       m_pipeline[PIPELINE_CACHE_NDX_CACHED] = m_pipelineBuilder.buildPipeline(m_renderSize, *m_renderPass, *m_cacheMerged);
+}
+
+MergeCacheTestInstance::~MergeCacheTestInstance (void)
+{
+       delete[] m_data;
+}
+
+} // anonymous
+
+tcu::TestCaseGroup* createCacheTests (tcu::TestContext& testCtx)
+{
+
+       de::MovePtr<tcu::TestCaseGroup> cacheTests (new tcu::TestCaseGroup(testCtx, "cache", "pipeline cache tests"));
+
+       // Graphics Pipeline Tests
+       {
+               de::MovePtr<tcu::TestCaseGroup> graphicsTests (new tcu::TestCaseGroup(testCtx, "graphics_tests", "Test pipeline cache with graphics pipeline."));
+
+               const VkShaderStageFlagBits testParamShaders0[] =
+               {
+                       VK_SHADER_STAGE_VERTEX_BIT,
+                       VK_SHADER_STAGE_FRAGMENT_BIT,
+               };
+               const VkShaderStageFlagBits testParamShaders1[] =
+               {
+                       VK_SHADER_STAGE_VERTEX_BIT,
+                       VK_SHADER_STAGE_GEOMETRY_BIT,
+                       VK_SHADER_STAGE_FRAGMENT_BIT,
+               };
+               const VkShaderStageFlagBits testParamShaders2[] =
+               {
+                       VK_SHADER_STAGE_VERTEX_BIT,
+                       VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
+                       VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
+                       VK_SHADER_STAGE_FRAGMENT_BIT,
+               };
+               const CacheTestParam* testParams[] =
+               {
+                       new CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0)),
+                       new CacheTestParam(testParamShaders1, DE_LENGTH_OF_ARRAY(testParamShaders1)),
+                       new CacheTestParam(testParamShaders2, DE_LENGTH_OF_ARRAY(testParamShaders2)),
+               };
+
+               for(deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
+               {
+                       graphicsTests->addChild(newTestCase<GraphicsCacheTest>(testCtx,testParams[i]));
+                       delete testParams[i];
+               }
+               cacheTests->addChild(graphicsTests.release());
+       }
+
+       // Graphics Pipeline Tests
+       {
+               de::MovePtr<tcu::TestCaseGroup> computeTests (new tcu::TestCaseGroup(testCtx, "compute_tests", "Test pipeline cache with compute pipeline."));
+
+               const VkShaderStageFlagBits testParamShaders0[] =
+               {
+                       VK_SHADER_STAGE_COMPUTE_BIT,
+               };
+
+               const CacheTestParam* testParams[] =
+               {
+                       new CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0)),
+               };
+               for(deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
+               {
+                       computeTests->addChild(newTestCase<ComputeCacheTest>(testCtx,testParams[i]));
+                       delete testParams[i];
+               }
+               cacheTests->addChild(computeTests.release());
+       }
+
+       // Misc Tests
+       {
+               de::MovePtr<tcu::TestCaseGroup> miscTests (new tcu::TestCaseGroup(testCtx, "misc_tests", "Misc tests that can not be categorized to other group."));
+
+               const VkShaderStageFlagBits testParamShaders[] =
+               {
+                       VK_SHADER_STAGE_VERTEX_BIT,
+                       VK_SHADER_STAGE_FRAGMENT_BIT,
+               };
+
+               CacheTestParam* testParam = new CacheTestParam(testParamShaders, DE_LENGTH_OF_ARRAY(testParamShaders));
+               miscTests->addChild(new MergeCacheTest(testCtx,
+                                                                                          "merge_cache_test",
+                                                                                          "Merge the caches test.",
+                                                                                          testParam));
+               delete testParam;
+
+               cacheTests->addChild(miscTests.release());
+       }
+
+       return cacheTests.release();
+}
+
+} // pipeline
+
+} // vkt
diff --git a/external/vulkancts/modules/vulkan/pipeline/vktPipelineCacheTests.hpp b/external/vulkancts/modules/vulkan/pipeline/vktPipelineCacheTests.hpp
new file mode 100644 (file)
index 0000000..705ea22
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef _VKTPIPELINECACHETESTS_HPP
+#define _VKTPIPELINECACHETESTS_HPP
+/*------------------------------------------------------------------------
+ * Vulkan Conformance Tests
+ * ------------------------
+ *
+ * Copyright (c) 2015 The Khronos Group Inc.
+ * Copyright (c) 2015 ARM Ltd.
+ *
+ * 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 Pipeline Cache Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "vktTestCase.hpp"
+
+namespace vkt
+{
+namespace pipeline
+{
+
+tcu::TestCaseGroup* createCacheTests (tcu::TestContext& testCtx);
+
+} // pipeline
+} // vkt
+
+#endif // _VKTPIPELINECACHETESTS_HPP
index c16ce51..6616716 100644 (file)
@@ -42,6 +42,7 @@
 #include "vktPipelineVertexInputTests.hpp"
 #include "vktPipelineTimestampTests.hpp"
 #include "vktPipelineEarlyFragmentTests.hpp"
+#include "vktPipelineCacheTests.hpp"
 #include "vktTestGroupUtil.hpp"
 
 namespace vkt
@@ -68,6 +69,7 @@ void createChildren (tcu::TestCaseGroup* pipelineTests)
        pipelineTests->addChild(createInputAssemblyTests(testCtx));
        pipelineTests->addChild(createTimestampTests    (testCtx));
        pipelineTests->addChild(createEarlyFragmentTests(testCtx));
+       pipelineTests->addChild(createCacheTests                (testCtx));
 }
 
 } // anonymous