Fix missing dependency on sparse binds
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / pipeline / vktPipelineCacheTests.cpp
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 ARM Ltd.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Pipeline Cache Tests
23  *//*--------------------------------------------------------------------*/
24
25 #include "vktPipelineCacheTests.hpp"
26 #include "vktPipelineClearUtil.hpp"
27 #include "vktPipelineImageUtil.hpp"
28 #include "vktPipelineVertexUtil.hpp"
29 #include "vktTestCase.hpp"
30 #include "vktTestCaseUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "vkMemUtil.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkQueryUtil.hpp"
36 #include "vkRef.hpp"
37 #include "vkRefUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "deUniquePtr.hpp"
43 #include "deMemory.h"
44 #include "tcuTestLog.hpp"
45
46 #include <sstream>
47 #include <vector>
48
49 namespace vkt
50 {
51 namespace pipeline
52 {
53
54 using namespace vk;
55
56 namespace
57 {
58
59 // helper functions
60
61 std::string getShaderFlagStr (const VkShaderStageFlags  shader,
62                                                           bool                                          isDescription)
63 {
64         std::ostringstream desc;
65         if (shader & VK_SHADER_STAGE_COMPUTE_BIT)
66         {
67                 desc << ((isDescription) ? "compute stage" : "compute_stage");
68         }
69         else
70         {
71                 desc << ((isDescription) ? "vertex stage" : "vertex_stage");
72                 if (shader & VK_SHADER_STAGE_GEOMETRY_BIT)
73                         desc << ((isDescription) ? " geometry stage" : "_geometry_stage");
74                 if (shader & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
75                         desc << ((isDescription) ? " tessellation control stage" : "_tessellation_control_stage");
76                 if (shader & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
77                         desc << ((isDescription) ? " tessellation evaluation stage" : "_tessellation_evaluation_stage");
78                 desc << ((isDescription) ? " fragment stage" : "_fragment_stage");
79         }
80
81         return desc.str();
82 }
83
84 // helper classes
85 class CacheTestParam
86 {
87 public:
88                                                                 CacheTestParam                          (PipelineConstructionType               pipelineConstructionType,
89                                                                                                                          const VkShaderStageFlags               shaders,
90                                                                                                                          bool                                                   compileCacheMissShaders,
91                                                                                                                          VkPipelineCacheCreateFlags             pipelineCacheCreateFlags = 0u);
92         virtual                                         ~CacheTestParam                         (void) = default;
93         virtual const std::string       generateTestName                        (void)  const;
94         virtual const std::string       generateTestDescription         (void)  const;
95         PipelineConstructionType        getPipelineConstructionType     (void)  const   { return m_pipelineConstructionType; }
96         VkShaderStageFlags                      getShaderFlags                          (void)  const   { return m_shaders; }
97         VkPipelineCacheCreateFlags      getPipelineCacheCreateFlags     (void)  const   { return m_pipelineCacheCreateFlags; }
98         bool                                            getCompileMissShaders           (void)  const   { return m_compileCacheMissShaders;     }
99
100 protected:
101
102         PipelineConstructionType        m_pipelineConstructionType;
103         VkShaderStageFlags                      m_shaders;
104         VkPipelineCacheCreateFlags      m_pipelineCacheCreateFlags;
105         bool                                            m_compileCacheMissShaders;
106 };
107
108 CacheTestParam::CacheTestParam (PipelineConstructionType pipelineConstructionType, const VkShaderStageFlags shaders, bool compileCacheMissShaders, VkPipelineCacheCreateFlags pipelineCacheCreateFlags)
109         : m_pipelineConstructionType    (pipelineConstructionType)
110         , m_shaders                                             (shaders)
111         , m_pipelineCacheCreateFlags(pipelineCacheCreateFlags)
112         , m_compileCacheMissShaders             (compileCacheMissShaders)
113 {
114 }
115
116 const std::string CacheTestParam::generateTestName (void) const
117 {
118         std::string name = getShaderFlagStr(m_shaders, false);
119         if (m_pipelineCacheCreateFlags == VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT) {
120                 name += "_externally_synchronized";
121         }
122         return name;
123 }
124
125 const std::string CacheTestParam::generateTestDescription (void) const
126 {
127         std::string description = getShaderFlagStr(m_shaders, true);
128         if (m_pipelineCacheCreateFlags == VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT) {
129                 description += "with externally synchronized bit";
130         }
131         return description;
132 }
133
134 template <class Test>
135 vkt::TestCase* newTestCase (tcu::TestContext&           testContext,
136                                                         const CacheTestParam*   testParam)
137 {
138         return new Test(testContext,
139                                         testParam->generateTestName().c_str(),
140                                         testParam->generateTestDescription().c_str(),
141                                         testParam);
142 }
143
144 Move<VkBuffer> createBufferAndBindMemory (Context& context, VkDeviceSize size, VkBufferUsageFlags usage, de::MovePtr<Allocation>* pAlloc)
145 {
146         const DeviceInterface&  vk                                      = context.getDeviceInterface();
147         const VkDevice                  vkDevice                        = context.getDevice();
148         const deUint32                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
149
150         const VkBufferCreateInfo vertexBufferParams =
151         {
152                 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,       // VkStructureType      sType;
153                 DE_NULL,                                    // const void*          pNext;
154                 0u,                                         // VkBufferCreateFlags  flags;
155                 size,                                       // VkDeviceSize         size;
156                 usage,                                      // VkBufferUsageFlags   usage;
157                 VK_SHARING_MODE_EXCLUSIVE,                  // VkSharingMode        sharingMode;
158                 1u,                                         // deUint32             queueFamilyCount;
159                 &queueFamilyIndex                           // const deUint32*      pQueueFamilyIndices;
160         };
161
162         Move<VkBuffer> vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
163
164         *pAlloc = context.getDefaultAllocator().allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
165         VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, (*pAlloc)->getMemory(), (*pAlloc)->getOffset()));
166
167         return vertexBuffer;
168 }
169
170 Move<VkImage> createImage2DAndBindMemory (Context&                                                      context,
171                                                                                   VkFormat                                                      format,
172                                                                                   deUint32                                                      width,
173                                                                                   deUint32                                                      height,
174                                                                                   VkImageUsageFlags                                     usage,
175                                                                                   VkSampleCountFlagBits                         sampleCount,
176                                                                                   de::details::MovePtr<Allocation>*     pAlloc)
177 {
178         const DeviceInterface&  vk                                      = context.getDeviceInterface();
179         const VkDevice                  vkDevice                        = context.getDevice();
180         const deUint32                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
181
182         const VkImageCreateInfo colorImageParams =
183         {
184                 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,    // VkStructureType      sType;
185                 DE_NULL,                                                                // const void*          pNext;
186                 0u,                                                                             // VkImageCreateFlags   flags;
187                 VK_IMAGE_TYPE_2D,                                               // VkImageType          imageType;
188                 format,                                                                 // VkFormat             format;
189                 { width, height, 1u },                                  // VkExtent3D           extent;
190                 1u,                                                                             // deUint32             mipLevels;
191                 1u,                                                                             // deUint32             arraySize;
192                 sampleCount,                                                    // deUint32             samples;
193                 VK_IMAGE_TILING_OPTIMAL,                                // VkImageTiling        tiling;
194                 usage,                                                                  // VkImageUsageFlags    usage;
195                 VK_SHARING_MODE_EXCLUSIVE,                              // VkSharingMode        sharingMode;
196                 1u,                                                                             // deUint32             queueFamilyCount;
197                 &queueFamilyIndex,                                              // const deUint32*      pQueueFamilyIndices;
198                 VK_IMAGE_LAYOUT_UNDEFINED,                              // VkImageLayout        initialLayout;
199         };
200
201         Move<VkImage> image = createImage(vk, vkDevice, &colorImageParams);
202
203         *pAlloc = context.getDefaultAllocator().allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any);
204         VK_CHECK(vk.bindImageMemory(vkDevice, *image, (*pAlloc)->getMemory(), (*pAlloc)->getOffset()));
205
206         return image;
207 }
208
209 // Test Classes
210 class CacheTest : public vkt::TestCase
211 {
212 public:
213                                                         CacheTest       (tcu::TestContext&              testContext,
214                                                                                  const std::string&             name,
215                                                                                  const std::string&             description,
216                                                                                  const CacheTestParam*  param)
217                                                           : vkt::TestCase (testContext, name, description)
218                                                           , m_param (*param)
219                                                           { }
220         virtual                                 ~CacheTest (void) { }
221 protected:
222         const CacheTestParam    m_param;
223 };
224
225 class CacheTestInstance : public vkt::TestInstance
226 {
227 public:
228         enum
229         {
230                 PIPELINE_CACHE_NDX_NO_CACHE,
231                 PIPELINE_CACHE_NDX_CACHED,
232                 PIPELINE_CACHE_NDX_COUNT,
233         };
234                                                         CacheTestInstance               (Context&                               context,
235                                                                                                          const CacheTestParam*  param);
236         virtual                                 ~CacheTestInstance              (void);
237         virtual tcu::TestStatus iterate                                 (void);
238 protected:
239         virtual tcu::TestStatus verifyTestResult                (void) = 0;
240         virtual void                    prepareCommandBuffer    (void) = 0;
241 protected:
242         const CacheTestParam*   m_param;
243         Move<VkCommandPool>             m_cmdPool;
244         Move<VkCommandBuffer>   m_cmdBuffer;
245         Move<VkPipelineCache>   m_cache;
246 };
247
248 CacheTestInstance::CacheTestInstance (Context&                          context,
249                                                                           const CacheTestParam* param)
250         : TestInstance  (context)
251         , m_param               (param)
252 {
253         const DeviceInterface&  vk                                      = m_context.getDeviceInterface();
254         const VkDevice                  vkDevice                        = m_context.getDevice();
255         const deUint32                  queueFamilyIndex        = context.getUniversalQueueFamilyIndex();
256
257         // Create command pool
258         m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
259
260         // Create command buffer
261         m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
262
263         // Create the Pipeline Cache
264         {
265                 const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
266                 {
267                         VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,   // VkStructureType             sType;
268                         DE_NULL,                                                                                // const void*                 pNext;
269                         m_param->getPipelineCacheCreateFlags(),                 // VkPipelineCacheCreateFlags  flags;
270                         0u,                                                                                             // deUintptr                   initialDataSize;
271                         DE_NULL,                                                                                // const void*                 pInitialData;
272                 };
273
274                 m_cache = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
275         }
276 }
277
278 CacheTestInstance::~CacheTestInstance (void)
279 {
280 }
281
282 tcu::TestStatus CacheTestInstance::iterate (void)
283 {
284         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
285         const VkDevice                  vkDevice        = m_context.getDevice();
286         const VkQueue                   queue           = m_context.getUniversalQueue();
287
288         prepareCommandBuffer();
289
290         submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
291
292         return verifyTestResult();
293 }
294
295 class GraphicsCacheTest : public CacheTest
296 {
297 public:
298                                                         GraphicsCacheTest       (tcu::TestContext&              testContext,
299                                                                                                  const std::string&             name,
300                                                                                                  const std::string&             description,
301                                                                                                  const CacheTestParam*  param)
302                                                                 : CacheTest (testContext, name, description, param)
303                                                                 { }
304         virtual                                 ~GraphicsCacheTest      (void) { }
305         virtual void                    initPrograms            (SourceCollections&             programCollection) const;
306         virtual void                    checkSupport            (Context&                               context) const;
307         virtual TestInstance*   createInstance          (Context&                               context) const;
308 };
309
310 class GraphicsCacheTestInstance : public CacheTestInstance
311 {
312 public:
313                                                         GraphicsCacheTestInstance   (Context&                           context,
314                                                                                                                  const CacheTestParam*  param);
315         virtual                                 ~GraphicsCacheTestInstance      (void);
316 protected:
317
318                         void                    preparePipelineWrapper          (GraphicsPipelineWrapper&       gpw,
319                                                                                                                  VkPipelineCache                        cache,
320                                                                                                                  bool                                           useMissShaders);
321         virtual void                    preparePipelines                        (void);
322                         void                    prepareRenderPass                       (VkFramebuffer framebuffer, VkPipeline pipeline);
323         virtual void                    prepareCommandBuffer            (void);
324         virtual tcu::TestStatus verifyTestResult                        (void);
325
326 protected:
327         const tcu::UVec2                                m_renderSize;
328         const VkFormat                                  m_colorFormat;
329         const VkFormat                                  m_depthFormat;
330         Move<VkPipelineLayout>                  m_pipelineLayout;
331
332         Move<VkImage>                                   m_depthImage;
333         de::MovePtr<Allocation>                 m_depthImageAlloc;
334         de::MovePtr<Allocation>                 m_colorImageAlloc[PIPELINE_CACHE_NDX_COUNT];
335         Move<VkImageView>                               m_depthAttachmentView;
336         VkImageMemoryBarrier                    m_imageLayoutBarriers[3];
337
338         Move<VkBuffer>                                  m_vertexBuffer;
339         de::MovePtr<Allocation>                 m_vertexBufferMemory;
340         std::vector<Vertex4RGBA>                m_vertices;
341
342         GraphicsPipelineWrapper                 m_pipeline[PIPELINE_CACHE_NDX_COUNT];
343         Move<VkRenderPass>                              m_renderPass;
344
345         Move<VkImage>                                   m_colorImage[PIPELINE_CACHE_NDX_COUNT];
346         Move<VkImageView>                               m_colorAttachmentView[PIPELINE_CACHE_NDX_COUNT];
347         Move<VkFramebuffer>                             m_framebuffer[PIPELINE_CACHE_NDX_COUNT];
348 };
349
350 void GraphicsCacheTest::initPrograms (SourceCollections& programCollection) const
351 {
352         enum ShaderCacheOpType
353         {
354                 SHADERS_CACHE_OP_HIT = 0,
355                 SHADERS_CACHE_OP_MISS,
356
357                 SHADERS_CACHE_OP_LAST
358         };
359
360         for (deUint32 shaderOpNdx = 0u; shaderOpNdx < SHADERS_CACHE_OP_LAST; shaderOpNdx++)
361         {
362                 const ShaderCacheOpType shaderOp = (ShaderCacheOpType)shaderOpNdx;
363
364                 if (shaderOp == SHADERS_CACHE_OP_MISS && !m_param.getCompileMissShaders())
365                         continue;
366
367                 const std::string missHitDiff = (shaderOp == SHADERS_CACHE_OP_HIT ? "" : " + 0.1");
368                 const std::string missSuffix = (shaderOp == SHADERS_CACHE_OP_HIT ? "" : "_miss");
369
370                 programCollection.glslSources.add("color_vert" + missSuffix) << glu::VertexSource(
371                         "#version 450\n"
372                         "layout(location = 0) in vec4 position;\n"
373                         "layout(location = 1) in vec4 color;\n"
374                         "layout(location = 0) out highp vec4 vtxColor;\n"
375                         "out gl_PerVertex { vec4 gl_Position; };\n"
376                         "void main (void)\n"
377                         "{\n"
378                         "  gl_Position = position;\n"
379                         "  vtxColor = color" + missHitDiff + ";\n"
380                         "}\n");
381
382                 programCollection.glslSources.add("color_frag" + missSuffix) << glu::FragmentSource(
383                         "#version 310 es\n"
384                         "layout(location = 0) in highp vec4 vtxColor;\n"
385                         "layout(location = 0) out highp vec4 fragColor;\n"
386                         "void main (void)\n"
387                         "{\n"
388                         "  fragColor = vtxColor" + missHitDiff + ";\n"
389                         "}\n");
390
391                 VkShaderStageFlags shaderFlag = m_param.getShaderFlags();
392                 if (shaderFlag & VK_SHADER_STAGE_GEOMETRY_BIT)
393                 {
394                         programCollection.glslSources.add("unused_geo" + missSuffix) << glu::GeometrySource(
395                                 "#version 450 \n"
396                                 "layout(triangles) in;\n"
397                                 "layout(triangle_strip, max_vertices = 3) out;\n"
398                                 "layout(location = 0) in highp vec4 in_vtxColor[];\n"
399                                 "layout(location = 0) out highp vec4 vtxColor;\n"
400                                 "out gl_PerVertex { vec4 gl_Position; };\n"
401                                 "in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
402                                 "void main (void)\n"
403                                 "{\n"
404                                 "  for(int ndx=0; ndx<3; ndx++)\n"
405                                 "  {\n"
406                                 "    gl_Position = gl_in[ndx].gl_Position;\n"
407                                 "    vtxColor    = in_vtxColor[ndx]" + missHitDiff + ";\n"
408                                 "    EmitVertex();\n"
409                                 "  }\n"
410                                 "  EndPrimitive();\n"
411                                 "}\n");
412                 }
413                 if (shaderFlag & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
414                 {
415                         programCollection.glslSources.add("basic_tcs" + missSuffix) << glu::TessellationControlSource(
416                                 "#version 450 \n"
417                                 "layout(vertices = 3) out;\n"
418                                 "layout(location = 0) in highp vec4 color[];\n"
419                                 "layout(location = 0) out highp vec4 vtxColor[];\n"
420                                 "out gl_PerVertex { vec4 gl_Position; } gl_out[3];\n"
421                                 "in gl_PerVertex { vec4 gl_Position; } gl_in[gl_MaxPatchVertices];\n"
422                                 "void main()\n"
423                                 "{\n"
424                                 "  gl_TessLevelOuter[0] = 4.0;\n"
425                                 "  gl_TessLevelOuter[1] = 4.0;\n"
426                                 "  gl_TessLevelOuter[2] = 4.0;\n"
427                                 "  gl_TessLevelInner[0] = 4.0;\n"
428                                 "  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
429                                 "  vtxColor[gl_InvocationID] = color[gl_InvocationID]" + missHitDiff + ";\n"
430                                 "}\n");
431                 }
432                 if (shaderFlag & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
433                 {
434                         programCollection.glslSources.add("basic_tes" + missSuffix) << glu::TessellationEvaluationSource(
435                                 "#version 450 \n"
436                                 "layout(triangles, fractional_even_spacing, ccw) in;\n"
437                                 "layout(location = 0) in highp vec4 colors[];\n"
438                                 "layout(location = 0) out highp vec4 vtxColor;\n"
439                                 "out gl_PerVertex { vec4 gl_Position; };\n"
440                                 "in gl_PerVertex { vec4 gl_Position; } gl_in[gl_MaxPatchVertices];\n"
441                                 "void main() \n"
442                                 "{\n"
443                                 "  float u = gl_TessCoord.x;\n"
444                                 "  float v = gl_TessCoord.y;\n"
445                                 "  float w = gl_TessCoord.z;\n"
446                                 "  vec4 pos = vec4(0);\n"
447                                 "  vec4 color = vec4(0)" + missHitDiff + ";\n"
448                                 "  pos.xyz += u * gl_in[0].gl_Position.xyz;\n"
449                                 "  color.xyz += u * colors[0].xyz;\n"
450                                 "  pos.xyz += v * gl_in[1].gl_Position.xyz;\n"
451                                 "  color.xyz += v * colors[1].xyz;\n"
452                                 "  pos.xyz += w * gl_in[2].gl_Position.xyz;\n"
453                                 "  color.xyz += w * colors[2].xyz;\n"
454                                 "  pos.w = 1.0;\n"
455                                 "  color.w = 1.0;\n"
456                                 "  gl_Position = pos;\n"
457                                 "  vtxColor = color;\n"
458                                 "}\n");
459                 }
460         }
461 }
462
463 void GraphicsCacheTest::checkSupport (Context& context) const
464 {
465         if (m_param.getShaderFlags() & VK_SHADER_STAGE_GEOMETRY_BIT)
466                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
467         if ((m_param.getShaderFlags() & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ||
468                 (m_param.getShaderFlags() & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
469                 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
470
471         checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_param.getPipelineConstructionType());
472 }
473
474 TestInstance* GraphicsCacheTest::createInstance (Context& context) const
475 {
476         return new GraphicsCacheTestInstance(context, &m_param);
477 }
478
479 GraphicsCacheTestInstance::GraphicsCacheTestInstance (Context&                          context,
480                                                                                                           const CacheTestParam* param)
481         : CacheTestInstance             (context,param)
482         , m_renderSize                  (32u, 32u)
483         , m_colorFormat                 (VK_FORMAT_R8G8B8A8_UNORM)
484         , m_depthFormat                 (VK_FORMAT_D16_UNORM)
485         , m_pipeline
486         {
487                 { context.getDeviceInterface(), context.getDevice(), param->getPipelineConstructionType() },
488                 { context.getDeviceInterface(), context.getDevice(), param->getPipelineConstructionType() },
489         }
490 {
491         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
492         const VkDevice                  vkDevice        = m_context.getDevice();
493
494         // Create vertex buffer
495         {
496                 m_vertexBuffer  = createBufferAndBindMemory(m_context, 1024u, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &m_vertexBufferMemory);
497
498                 m_vertices              = createOverlappingQuads();
499                 // Load vertices into vertex buffer
500                 deMemcpy(m_vertexBufferMemory->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
501                 flushAlloc(vk, vkDevice, *m_vertexBufferMemory);
502         }
503
504         // Create render pass
505         m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat, m_depthFormat);
506
507         const VkComponentMapping ComponentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
508         // Create color image
509         {
510                 m_colorImage[PIPELINE_CACHE_NDX_NO_CACHE]       = createImage2DAndBindMemory(m_context,
511                                                                                                                                                                  m_colorFormat,
512                                                                                                                                                                  m_renderSize.x(),
513                                                                                                                                                                  m_renderSize.y(),
514                                                                                                                                                                  VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
515                                                                                                                                                                  VK_SAMPLE_COUNT_1_BIT,
516                                                                                                                                                                  &m_colorImageAlloc[PIPELINE_CACHE_NDX_NO_CACHE]);
517                 m_colorImage[PIPELINE_CACHE_NDX_CACHED]         = createImage2DAndBindMemory(m_context,
518                                                                                                                                                                  m_colorFormat,
519                                                                                                                                                                  m_renderSize.x(),
520                                                                                                                                                                  m_renderSize.y(),
521                                                                                                                                                                  VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
522                                                                                                                                                                  VK_SAMPLE_COUNT_1_BIT,
523                                                                                                                                                                  &m_colorImageAlloc[PIPELINE_CACHE_NDX_CACHED]);
524         }
525
526         // Create depth image
527         {
528                 m_depthImage = createImage2DAndBindMemory(m_context,
529                                                                                                   m_depthFormat,
530                                                                                                   m_renderSize.x(),
531                                                                                                   m_renderSize.y(),
532                                                                                                   VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
533                                                                                                   VK_SAMPLE_COUNT_1_BIT,
534                                                                                                   &m_depthImageAlloc);
535         }
536
537         // Set up image layout transition barriers
538         {
539                 VkImageMemoryBarrier colorImageBarrier =
540                 {
541                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
542                         DE_NULL,                                                                                        // const void*                          pNext;
543                         0u,                                                                                                     // VkAccessFlags                        srcAccessMask;
544                         VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,                           // VkAccessFlags                        dstAccessMask;
545                         VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                        oldLayout;
546                         VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,                       // VkImageLayout                        newLayout;
547                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
548                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     dstQueueFamilyIndex;
549                         *m_colorImage[PIPELINE_CACHE_NDX_NO_CACHE],                     // VkImage                                      image;
550                         { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },          // VkImageSubresourceRange      subresourceRange;
551                 };
552
553                 m_imageLayoutBarriers[0] = colorImageBarrier;
554
555                 colorImageBarrier.image = *m_colorImage[PIPELINE_CACHE_NDX_CACHED];
556                 m_imageLayoutBarriers[1] = colorImageBarrier;
557
558                 const VkImageMemoryBarrier depthImageBarrier =
559                 {
560                         VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,                         // VkStructureType                      sType;
561                         DE_NULL,                                                                                        // const void*                          pNext;
562                         0u,                                                                                                     // VkAccessFlags                        srcAccessMask;
563                         VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,           // VkAccessFlags                        dstAccessMask;
564                         VK_IMAGE_LAYOUT_UNDEFINED,                                                      // VkImageLayout                        oldLayout;
565                         VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,       // VkImageLayout                        newLayout;
566                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     srcQueueFamilyIndex;
567                         VK_QUEUE_FAMILY_IGNORED,                                                        // deUint32                                     dstQueueFamilyIndex;
568                         *m_depthImage,                                                                          // VkImage                                      image;
569                         { VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u },          // VkImageSubresourceRange      subresourceRange;
570                 };
571
572                 m_imageLayoutBarriers[2] = depthImageBarrier;
573         }
574         // Create color attachment view
575         {
576                 VkImageViewCreateInfo colorAttachmentViewParams =
577                 {
578                         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,               // VkStructureType          sType;
579                         DE_NULL,                                                                                // const void*              pNext;
580                         0u,                                                                                             // VkImageViewCreateFlags   flags;
581                         *m_colorImage[PIPELINE_CACHE_NDX_NO_CACHE],             // VkImage                  image;
582                         VK_IMAGE_VIEW_TYPE_2D,                                                  // VkImageViewType          viewType;
583                         m_colorFormat,                                                                  // VkFormat                 format;
584                         ComponentMappingRGBA,                                                   // VkComponentMapping       components;
585                         { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },  // VkImageSubresourceRange  subresourceRange;
586                 };
587
588                 m_colorAttachmentView[PIPELINE_CACHE_NDX_NO_CACHE] = createImageView(vk, vkDevice, &colorAttachmentViewParams);
589
590                 colorAttachmentViewParams.image = *m_colorImage[PIPELINE_CACHE_NDX_CACHED];
591                 m_colorAttachmentView[PIPELINE_CACHE_NDX_CACHED] = createImageView(vk, vkDevice, &colorAttachmentViewParams);
592         }
593
594         // Create depth attachment view
595         {
596                 const VkImageViewCreateInfo depthAttachmentViewParams =
597                 {
598                         VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,               // VkStructureType          sType;
599                         DE_NULL,                                                                                // const void*              pNext;
600                         0u,                                                                                             // VkImageViewCreateFlags   flags;
601                         *m_depthImage,                                                                  // VkImage                  image;
602                         VK_IMAGE_VIEW_TYPE_2D,                                                  // VkImageViewType          viewType;
603                         m_depthFormat,                                                                  // VkFormat                 format;
604                         ComponentMappingRGBA,                                                   // VkComponentMapping       components;
605                         { VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u },  // VkImageSubresourceRange  subresourceRange;
606                 };
607
608                 m_depthAttachmentView = createImageView(vk, vkDevice, &depthAttachmentViewParams);
609         }
610
611         // Create framebuffer
612         {
613                 VkImageView attachmentBindInfos[2] =
614                 {
615                         *m_colorAttachmentView[PIPELINE_CACHE_NDX_NO_CACHE],
616                         *m_depthAttachmentView,
617                 };
618
619                 const VkFramebufferCreateInfo framebufferParams =
620                 {
621                         VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,      // VkStructureType              sType;
622                         DE_NULL,                                                                        // const void*                  pNext;
623                         0u,                                                                                     // VkFramebufferCreateFlags     flags;
624                         *m_renderPass,                                                          // VkRenderPass                 renderPass;
625                         2u,                                                                                     // deUint32                     attachmentCount;
626                         attachmentBindInfos,                                            // const VkImageView*           pAttachments;
627                         (deUint32)m_renderSize.x(),                                     // deUint32                     width;
628                         (deUint32)m_renderSize.y(),                                     // deUint32                     height;
629                         1u,                                                                                     // deUint32                     layers;
630                 };
631
632                 m_framebuffer[PIPELINE_CACHE_NDX_NO_CACHE] = createFramebuffer(vk, vkDevice, &framebufferParams);
633
634                 attachmentBindInfos[0] = *m_colorAttachmentView[PIPELINE_CACHE_NDX_CACHED];
635                 m_framebuffer[PIPELINE_CACHE_NDX_CACHED] = createFramebuffer(vk, vkDevice, &framebufferParams);
636         }
637
638         // Create pipeline layout
639         {
640                 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
641                 {
642                         VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,  // VkStructureType                                      sType;
643                         DE_NULL,                                                                                // const void*                                          pNext;
644                         0u,                                                                                             // VkPipelineLayoutCreateFlags          flags;
645                         0u,                                                                                             // deUint32                                                     setLayoutCount;
646                         DE_NULL,                                                                                // const VkDescriptorSetLayout*         pSetLayouts;
647                         0u,                                                                                             // deUint32                                                     pushConstantRangeCount;
648                         DE_NULL                                                                                 // const VkPushConstantRange*           pPushConstantRanges;
649                 };
650
651                 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
652         }
653 }
654
655 GraphicsCacheTestInstance::~GraphicsCacheTestInstance (void)
656 {
657 }
658
659 void GraphicsCacheTestInstance::preparePipelineWrapper(GraphicsPipelineWrapper& gpw,
660                                                                                                            VkPipelineCache                      cache,
661                                                                                                            bool                                         useMissShaders = false)
662 {
663         static const VkPipelineDepthStencilStateCreateInfo defaultDepthStencilState
664         {
665                 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,             // VkStructureType                                                      sType;
666                 DE_NULL,                                                                                                                // const void*                                                          pNext;
667                 0u,                                                                                                                             // VkPipelineDepthStencilStateCreateFlags       flags;
668                 VK_TRUE,                                                                                                                // VkBool32                                                                     depthTestEnable;
669                 VK_TRUE,                                                                                                                // VkBool32                                                                     depthWriteEnable;
670                 VK_COMPARE_OP_LESS_OR_EQUAL,                                                                    // VkCompareOp                                                          depthCompareOp;
671                 VK_FALSE,                                                                                                               // VkBool32                                                                     depthBoundsTestEnable;
672                 VK_FALSE,                                                                                                               // VkBool32                                                                     stencilTestEnable;
673                 {                                                                                                                               // VkStencilOpState             front;
674                         VK_STENCIL_OP_KEEP,                                                                                             // VkStencilOp          failOp;
675                         VK_STENCIL_OP_KEEP,                                                                                             // VkStencilOp          passOp;
676                         VK_STENCIL_OP_KEEP,                                                                                             // VkStencilOp          depthFailOp;
677                         VK_COMPARE_OP_NEVER,                                                                                    // VkCompareOp          compareOp;
678                         0u,                                                                                                                             // deUint32                     compareMask;
679                         0u,                                                                                                                             // deUint32                     writeMask;
680                         0u,                                                                                                                             // deUint32                     reference;
681                 },
682                 {                                                                                                                               // VkStencilOpState             back;
683                         VK_STENCIL_OP_KEEP,                                                                                             // VkStencilOp          failOp;
684                         VK_STENCIL_OP_KEEP,                                                                                             // VkStencilOp          passOp;
685                         VK_STENCIL_OP_KEEP,                                                                                             // VkStencilOp          depthFailOp;
686                         VK_COMPARE_OP_NEVER,                                                                                    // VkCompareOp          compareOp;
687                         0u,                                                                                                                             // deUint32                     compareMask;
688                         0u,                                                                                                                             // deUint32                     writeMask;
689                         0u,                                                                                                                             // deUint32                     reference;
690                 },
691                 0.0f,                                                                                                                   // float                                                                        minDepthBounds;
692                 1.0f,                                                                                                                   // float                                                                        maxDepthBounds;
693         };
694
695         static const VkVertexInputBindingDescription defaultVertexInputBindingDescription
696         {
697                 0u,                                                                                                                             // deUint32                                     binding;
698                 sizeof(Vertex4RGBA),                                                                                    // deUint32                                     strideInBytes;
699                 VK_VERTEX_INPUT_RATE_VERTEX,                                                                    // VkVertexInputRate            inputRate;
700         };
701
702         static const VkVertexInputAttributeDescription defaultVertexInputAttributeDescriptions[]
703         {
704                 {
705                         0u,                                                                                                                     // deUint32                                     location;
706                         0u,                                                                                                                     // deUint32                                     binding;
707                         VK_FORMAT_R32G32B32A32_SFLOAT,                                                          // VkFormat                                     format;
708                         0u                                                                                                                      // deUint32                                     offsetInBytes;
709                 },
710                 {
711                         1u,                                                                                                                     // deUint32                                     location;
712                         0u,                                                                                                                     // deUint32                                     binding;
713                         VK_FORMAT_R32G32B32A32_SFLOAT,                                                          // VkFormat                                     format;
714                         DE_OFFSET_OF(Vertex4RGBA, color),                                                       // deUint32                                     offsetInBytes;
715                 }
716         };
717
718         static const VkPipelineVertexInputStateCreateInfo defaultVertexInputStateParams
719         {
720                 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,              // VkStructureType                                                              sType;
721                 DE_NULL,                                                                                                                // const void*                                                                  pNext;
722                 0u,                                                                                                                             // VkPipelineVertexInputStateCreateFlags                flags;
723                 1u,                                                                                                                             // deUint32                                                                             vertexBindingDescriptionCount;
724                 &defaultVertexInputBindingDescription,                                                  // const VkVertexInputBindingDescription*               pVertexBindingDescriptions;
725                 2u,                                                                                                                             // deUint32                                                                             vertexAttributeDescriptionCount;
726                 defaultVertexInputAttributeDescriptions,                                                // const VkVertexInputAttributeDescription*             pVertexAttributeDescriptions;
727         };
728
729         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
730         const VkDevice                  vkDevice        = m_context.getDevice();
731         const std::string               postfix         = useMissShaders ? "_miss" : "";
732
733         auto createModule = [&vk, vkDevice, &postfix](Context& context, std::string shaderName)
734         {
735                 return createShaderModule(vk, vkDevice, context.getBinaryCollection().get(shaderName + postfix), 0);
736         };
737
738         // Bind shader stages
739         Move<VkShaderModule> vertShaderModule = createModule(m_context, "color_vert");
740         Move<VkShaderModule> fragShaderModule = createModule(m_context, "color_frag");
741         Move<VkShaderModule> tescShaderModule;
742         Move<VkShaderModule> teseShaderModule;
743         Move<VkShaderModule> geomShaderModule;
744
745         if (m_param->getShaderFlags() & VK_SHADER_STAGE_GEOMETRY_BIT)
746                 geomShaderModule = createModule(m_context, "unused_geo");
747         if (m_param->getShaderFlags() & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
748                 tescShaderModule = createModule(m_context, "basic_tcs");
749         if (m_param->getShaderFlags() & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
750                 teseShaderModule = createModule(m_context, "basic_tes");
751
752         const std::vector<VkViewport>   viewport        { makeViewport(m_renderSize) };
753         const std::vector<VkRect2D>             scissor         { makeRect2D(m_renderSize) };
754
755         gpw.setDefaultTopology((m_param->getShaderFlags() & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
756                                                    ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
757                 .setDefaultRasterizationState()
758                 .setDefaultColorBlendState()
759                 .setDefaultMultisampleState()
760                 .setupVertexInputState(&defaultVertexInputStateParams)
761                 .setupPreRasterizationShaderState(viewport,
762                                                                                   scissor,
763                                                                                   *m_pipelineLayout,
764                                                                                   *m_renderPass,
765                                                                                   0u,
766                                                                                   *vertShaderModule,
767                                                                                   DE_NULL,
768                                                                                   *tescShaderModule,
769                                                                                   *teseShaderModule,
770                                                                                   *geomShaderModule)
771                 .setupFragmentShaderState(*m_pipelineLayout, *m_renderPass, 0u, *fragShaderModule, &defaultDepthStencilState)
772                 .setupFragmentOutputState(*m_renderPass)
773                 .setMonolithicPipelineLayout(*m_pipelineLayout)
774                 .buildPipeline(cache);
775 }
776
777 void GraphicsCacheTestInstance::preparePipelines (void)
778 {
779         preparePipelineWrapper(m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], *m_cache);
780         preparePipelineWrapper(m_pipeline[PIPELINE_CACHE_NDX_CACHED], *m_cache);
781 }
782
783 void GraphicsCacheTestInstance::prepareRenderPass (VkFramebuffer framebuffer, VkPipeline pipeline)
784 {
785         const DeviceInterface&  vk                                                      = m_context.getDeviceInterface();
786
787         const VkClearValue              attachmentClearValues[2]        =
788         {
789                 defaultClearValue(m_colorFormat),
790                 defaultClearValue(m_depthFormat),
791         };
792
793         beginRenderPass(vk, *m_cmdBuffer, *m_renderPass, framebuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), 2u, attachmentClearValues);
794
795         vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
796         VkDeviceSize offsets = 0u;
797         vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &offsets);
798         vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1u, 0u, 0u);
799
800         endRenderPass(vk, *m_cmdBuffer);
801 }
802
803 void GraphicsCacheTestInstance::prepareCommandBuffer (void)
804 {
805         const DeviceInterface& vk = m_context.getDeviceInterface();
806
807         preparePipelines();
808
809         beginCommandBuffer(vk, *m_cmdBuffer, 0u);
810
811         vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, (VkDependencyFlags)0,
812                 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(m_imageLayoutBarriers), m_imageLayoutBarriers);
813
814         prepareRenderPass(*m_framebuffer[PIPELINE_CACHE_NDX_NO_CACHE], m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE].getPipeline());
815
816         // After the first render pass, the images are in correct layouts
817
818         prepareRenderPass(*m_framebuffer[PIPELINE_CACHE_NDX_CACHED], m_pipeline[PIPELINE_CACHE_NDX_CACHED].getPipeline());
819
820         endCommandBuffer(vk, *m_cmdBuffer);
821 }
822
823 tcu::TestStatus GraphicsCacheTestInstance::verifyTestResult (void)
824 {
825         const DeviceInterface&                  vk                                      = m_context.getDeviceInterface();
826         const VkDevice                                  vkDevice                        = m_context.getDevice();
827         const deUint32                                  queueFamilyIndex        = m_context.getUniversalQueueFamilyIndex();
828
829         const VkQueue                                   queue                           = m_context.getUniversalQueue();
830         de::MovePtr<tcu::TextureLevel>  resultNoCache           = readColorAttachment(vk,
831                                                                                                                                                           vkDevice,
832                                                                                                                                                           queue,
833                                                                                                                                                           queueFamilyIndex,
834                                                                                                                                                           m_context.getDefaultAllocator(),
835                                                                                                                                                           *m_colorImage[PIPELINE_CACHE_NDX_NO_CACHE],
836                                                                                                                                                           m_colorFormat,
837                                                                                                                                                           m_renderSize);
838         de::MovePtr<tcu::TextureLevel>  resultCache                     = readColorAttachment(vk,
839                                                                                                                                                           vkDevice,
840                                                                                                                                                           queue,
841                                                                                                                                                           queueFamilyIndex,
842                                                                                                                                                           m_context.getDefaultAllocator(),
843                                                                                                                                                           *m_colorImage[PIPELINE_CACHE_NDX_CACHED],
844                                                                                                                                                           m_colorFormat,
845                                                                                                                                                           m_renderSize);
846
847         bool compareOk = tcu::intThresholdCompare(m_context.getTestContext().getLog(),
848                                                                                           "IntImageCompare",
849                                                                                           "Image comparison",
850                                                                                           resultNoCache->getAccess(),
851                                                                                           resultCache->getAccess(),
852                                                                                           tcu::UVec4(1, 1, 1, 1),
853                                                                                           tcu::COMPARE_LOG_RESULT);
854
855         if (compareOk)
856                 return tcu::TestStatus::pass("Render images w/o cached pipeline match.");
857         else
858                 return tcu::TestStatus::fail("Render Images mismatch.");
859 }
860
861 class ComputeCacheTest : public CacheTest
862 {
863 public:
864                                                         ComputeCacheTest        (tcu::TestContext&              testContext,
865                                                                                                  const std::string&             name,
866                                                                                                  const std::string&             description,
867                                                                                                  const CacheTestParam*  param)
868                                                                 : CacheTest (testContext, name, description, param)
869                                                                 { }
870         virtual                                 ~ComputeCacheTest       (void) { }
871         virtual void                    initPrograms            (SourceCollections&             programCollection) const;
872         virtual TestInstance*   createInstance          (Context&                               context) const;
873 };
874
875 class ComputeCacheTestInstance : public CacheTestInstance
876 {
877 public:
878                                                         ComputeCacheTestInstance        (Context&                               context,
879                                                                                                                  const CacheTestParam*  param);
880         virtual                                 ~ComputeCacheTestInstance       (void);
881         virtual void                    prepareCommandBuffer            (void);
882 protected:
883         virtual tcu::TestStatus verifyTestResult                        (void);
884                         void                    buildBuffers                            (void);
885                         void                    buildDescriptorSets                     (deUint32 ndx);
886                         void                    buildShader                                     (void);
887                         void                    buildPipeline                           (deUint32 ndx);
888 protected:
889         Move<VkBuffer>                          m_inputBuf;
890         de::MovePtr<Allocation>         m_inputBufferAlloc;
891         Move<VkShaderModule>            m_computeShaderModule;
892
893         Move<VkBuffer>                          m_outputBuf[PIPELINE_CACHE_NDX_COUNT];
894         de::MovePtr<Allocation>         m_outputBufferAlloc[PIPELINE_CACHE_NDX_COUNT];
895
896         Move<VkDescriptorPool>          m_descriptorPool[PIPELINE_CACHE_NDX_COUNT];
897         Move<VkDescriptorSetLayout>     m_descriptorSetLayout[PIPELINE_CACHE_NDX_COUNT];
898         Move<VkDescriptorSet>           m_descriptorSet[PIPELINE_CACHE_NDX_COUNT];
899
900         Move<VkPipelineLayout>          m_pipelineLayout[PIPELINE_CACHE_NDX_COUNT];
901         Move<VkPipeline>                        m_pipeline[PIPELINE_CACHE_NDX_COUNT];
902 };
903
904 void ComputeCacheTest::initPrograms (SourceCollections& programCollection) const
905 {
906         programCollection.glslSources.add("basic_compute") << glu::ComputeSource(
907                 "#version 310 es\n"
908                 "layout(local_size_x = 1) in;\n"
909                 "layout(std430) buffer;\n"
910                 "layout(binding = 0) readonly buffer Input0\n"
911                 "{\n"
912                 "  vec4 elements[];\n"
913                 "} input_data0;\n"
914                 "layout(binding = 1) writeonly buffer Output\n"
915                 "{\n"
916                 "  vec4 elements[];\n"
917                 "} output_data;\n"
918                 "void main()\n"
919                 "{\n"
920                 "  uint ident = gl_GlobalInvocationID.x;\n"
921                 "  output_data.elements[ident] = input_data0.elements[ident] * input_data0.elements[ident];\n"
922                 "}");
923 }
924
925 TestInstance* ComputeCacheTest::createInstance (Context& context) const
926 {
927         return new ComputeCacheTestInstance(context, &m_param);
928 }
929
930 void ComputeCacheTestInstance::buildBuffers (void)
931 {
932         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
933         const VkDevice                  vkDevice        = m_context.getDevice();
934
935         // Create buffer object, allocate storage, and generate input data
936         const VkDeviceSize              size            = sizeof(tcu::Vec4) * 128u;
937         m_inputBuf = createBufferAndBindMemory(m_context, size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, &m_inputBufferAlloc);
938
939         // Initialize input buffer
940         tcu::Vec4* pVec = reinterpret_cast<tcu::Vec4*>(m_inputBufferAlloc->getHostPtr());
941         for (deUint32 ndx = 0u; ndx < 128u; ndx++)
942         {
943                 for (deUint32 component = 0u; component < 4u; component++)
944                         pVec[ndx][component]= (float)(ndx * (component + 1u));
945         }
946         flushAlloc(vk, vkDevice, *m_inputBufferAlloc);
947
948         // Clear the output buffer
949         for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
950         {
951                 m_outputBuf[ndx] = createBufferAndBindMemory(m_context, size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, &m_outputBufferAlloc[ndx]);
952
953                 pVec = reinterpret_cast<tcu::Vec4*>(m_outputBufferAlloc[ndx]->getHostPtr());
954
955                 for (deUint32 i = 0; i < (size / sizeof(tcu::Vec4)); i++)
956                         pVec[i] = tcu::Vec4(0.0f);
957
958                 flushAlloc(vk, vkDevice, *m_outputBufferAlloc[ndx]);
959         }
960 }
961
962 void ComputeCacheTestInstance::buildDescriptorSets (deUint32 ndx)
963 {
964         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
965         const VkDevice                  vkDevice        = m_context.getDevice();
966
967         // Create descriptor set layout
968         DescriptorSetLayoutBuilder descLayoutBuilder;
969
970         for (deUint32 bindingNdx = 0u; bindingNdx < 2u; bindingNdx++)
971                 descLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
972
973         m_descriptorSetLayout[ndx] = descLayoutBuilder.build(vk, vkDevice);
974
975         std::vector<VkDescriptorBufferInfo> descriptorInfos;
976         descriptorInfos.push_back(makeDescriptorBufferInfo(*m_inputBuf, 0u, sizeof(tcu::Vec4) * 128u));
977         descriptorInfos.push_back(makeDescriptorBufferInfo(*m_outputBuf[ndx], 0u, sizeof(tcu::Vec4) * 128u));
978
979         // Create descriptor pool
980         m_descriptorPool[ndx] = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2u).build(vk,
981                                                                                                                                                                                                                  vkDevice,
982                                                                                                                                                                                                                  VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
983                                                                                                                                                                                                                  1u);
984
985         // Create descriptor set
986         const VkDescriptorSetAllocateInfo descriptorSetAllocInfo =
987         {
988                 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType                 sType;
989                 DE_NULL,                                                                                // const void*                     pNext;
990                 *m_descriptorPool[ndx],                                                 // VkDescriptorPool                descriptorPool;
991                 1u,                                                                                             // deUint32                        setLayoutCount;
992                 &m_descriptorSetLayout[ndx].get(),                              // const VkDescriptorSetLayout*    pSetLayouts;
993         };
994         m_descriptorSet[ndx] = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocInfo);
995
996         DescriptorSetUpdateBuilder  builder;
997         for (deUint32 descriptorNdx = 0u; descriptorNdx < 2u; descriptorNdx++)
998         {
999                 builder.writeSingle(*m_descriptorSet[ndx],
1000                                                         DescriptorSetUpdateBuilder::Location::binding(descriptorNdx),
1001                                                         VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
1002                                                         &descriptorInfos[descriptorNdx]);
1003         }
1004         builder.update(vk, vkDevice);
1005 }
1006
1007 void ComputeCacheTestInstance::buildShader (void)
1008 {
1009         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1010         const VkDevice                  vkDevice        = m_context.getDevice();
1011
1012         // Create compute shader
1013         VkShaderModuleCreateInfo shaderModuleCreateInfo =
1014         {
1015                 VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,                                                                    // VkStructureType             sType;
1016                 DE_NULL,                                                                                                                                                // const void*                 pNext;
1017                 0u,                                                                                                                                                             // VkShaderModuleCreateFlags   flags;
1018                 m_context.getBinaryCollection().get("basic_compute").getSize(),                                 // deUintptr                   codeSize;
1019                 (deUint32*)m_context.getBinaryCollection().get("basic_compute").getBinary(),    // const deUint32*             pCode;
1020         };
1021         m_computeShaderModule = createShaderModule(vk, vkDevice, &shaderModuleCreateInfo);
1022 }
1023
1024 void ComputeCacheTestInstance::buildPipeline (deUint32 ndx)
1025 {
1026         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1027         const VkDevice                  vkDevice        = m_context.getDevice();
1028
1029         // Create compute pipeline layout
1030         const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1031         {
1032                 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,  // VkStructureType                 sType;
1033                 DE_NULL,                                                                                // const void*                     pNext;
1034                 0u,                                                                                             // VkPipelineLayoutCreateFlags     flags;
1035                 1u,                                                                                             // deUint32                        setLayoutCount;
1036                 &m_descriptorSetLayout[ndx].get(),                              // const VkDescriptorSetLayout*    pSetLayouts;
1037                 0u,                                                                                             // deUint32                        pushConstantRangeCount;
1038                 DE_NULL,                                                                                // const VkPushConstantRange*      pPushConstantRanges;
1039         };
1040
1041         m_pipelineLayout[ndx] = createPipelineLayout(vk, vkDevice, &pipelineLayoutCreateInfo);
1042
1043         const VkPipelineShaderStageCreateInfo stageCreateInfo =
1044         {
1045                 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,    // VkStructureType                     sType;
1046                 DE_NULL,                                                                                                // const void*                         pNext;
1047                 0u,                                                                                                             // VkPipelineShaderStageCreateFlags    flags;
1048                 VK_SHADER_STAGE_COMPUTE_BIT,                                                    // VkShaderStageFlagBits               stage;
1049                 *m_computeShaderModule,                                                                 // VkShaderModule                      module;
1050                 "main",                                                                                                 // const char*                         pName;
1051                 DE_NULL,                                                                                                // const VkSpecializationInfo*         pSpecializationInfo;
1052         };
1053
1054         const VkComputePipelineCreateInfo pipelineCreateInfo =
1055         {
1056                 VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,         // VkStructureType                 sType;
1057                 DE_NULL,                                                                                        // const void*                     pNext;
1058                 0u,                                                                                                     // VkPipelineCreateFlags           flags;
1059                 stageCreateInfo,                                                                        // VkPipelineShaderStageCreateInfo stage;
1060                 *m_pipelineLayout[ndx],                                                         // VkPipelineLayout                layout;
1061                 (VkPipeline)0,                                                                          // VkPipeline                      basePipelineHandle;
1062                 0u,                                                                                                     // deInt32                         basePipelineIndex;
1063         };
1064
1065         m_pipeline[ndx] = createComputePipeline(vk, vkDevice, *m_cache, &pipelineCreateInfo);
1066 }
1067
1068 ComputeCacheTestInstance::ComputeCacheTestInstance (Context&                            context,
1069                                                                                                         const CacheTestParam*   param)
1070         : CacheTestInstance (context, param)
1071 {
1072         buildBuffers();
1073
1074         buildDescriptorSets(PIPELINE_CACHE_NDX_NO_CACHE);
1075
1076         buildDescriptorSets(PIPELINE_CACHE_NDX_CACHED);
1077
1078         buildShader();
1079
1080         buildPipeline(PIPELINE_CACHE_NDX_NO_CACHE);
1081
1082         buildPipeline(PIPELINE_CACHE_NDX_CACHED);
1083 }
1084
1085 ComputeCacheTestInstance::~ComputeCacheTestInstance (void)
1086 {
1087 }
1088
1089 void ComputeCacheTestInstance::prepareCommandBuffer (void)
1090 {
1091         const DeviceInterface& vk = m_context.getDeviceInterface();
1092
1093         beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1094
1095         for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
1096         {
1097                 vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline[ndx]);
1098                 vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout[ndx], 0u, 1u, &m_descriptorSet[ndx].get(), 0u, DE_NULL);
1099                 vk.cmdDispatch(*m_cmdBuffer, 128u, 1u, 1u);
1100         }
1101
1102         endCommandBuffer(vk, *m_cmdBuffer);
1103 }
1104
1105 tcu::TestStatus ComputeCacheTestInstance::verifyTestResult (void)
1106 {
1107         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1108         const VkDevice                  vkDevice        = m_context.getDevice();
1109
1110         // Read the content of output buffers
1111         invalidateAlloc(vk, vkDevice, *m_outputBufferAlloc[PIPELINE_CACHE_NDX_NO_CACHE]);
1112
1113         invalidateAlloc(vk, vkDevice, *m_outputBufferAlloc[PIPELINE_CACHE_NDX_CACHED]);
1114         // Compare the content
1115         deUint8* bufNoCache = reinterpret_cast<deUint8*>(m_outputBufferAlloc[PIPELINE_CACHE_NDX_NO_CACHE]->getHostPtr());
1116         deUint8* bufCached  = reinterpret_cast<deUint8*>(m_outputBufferAlloc[PIPELINE_CACHE_NDX_CACHED]->getHostPtr());
1117         for (deUint32 ndx = 0u; ndx < sizeof(tcu::Vec4) * 128u; ndx++)
1118         {
1119                 if (bufNoCache[ndx] != bufCached[ndx])
1120                 {
1121                         return tcu::TestStatus::fail("Output buffers w/o cached pipeline mismatch.");
1122                 }
1123         }
1124
1125         return tcu::TestStatus::pass("Output buffers w/o cached pipeline match.");
1126 }
1127
1128 class PipelineFromCacheTest : public GraphicsCacheTest
1129 {
1130 public:
1131                                                         PipelineFromCacheTest           (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param);
1132         virtual                                 ~PipelineFromCacheTest          (void) { }
1133         virtual TestInstance*   createInstance                          (Context& context) const;
1134 };
1135
1136 PipelineFromCacheTest::PipelineFromCacheTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param)
1137         : GraphicsCacheTest(testContext, name, description, param)
1138 {
1139 }
1140
1141 class PipelineFromCacheTestInstance : public GraphicsCacheTestInstance
1142 {
1143 public:
1144                                                         PipelineFromCacheTestInstance   (Context& context, const CacheTestParam* param);
1145         virtual                                 ~PipelineFromCacheTestInstance  (void);
1146
1147 protected:
1148         void                                    preparePipelines(void);
1149
1150 protected:
1151         Move<VkPipelineCache>   m_newCache;
1152         deUint8*                                m_data;
1153 };
1154
1155 TestInstance* PipelineFromCacheTest::createInstance (Context& context) const
1156 {
1157         return new PipelineFromCacheTestInstance(context, &m_param);
1158 }
1159
1160 PipelineFromCacheTestInstance::PipelineFromCacheTestInstance (Context& context, const CacheTestParam* param)
1161         : GraphicsCacheTestInstance     (context, param)
1162         , m_data                                        (DE_NULL)
1163 {
1164         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1165         const VkDevice                  vkDevice        = m_context.getDevice();
1166
1167         // Create more pipeline caches
1168         {
1169                 size_t dataSize = 0u;
1170
1171                 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, DE_NULL));
1172
1173                 m_data = new deUint8[dataSize];
1174                 DE_ASSERT(m_data);
1175                 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, (void*)m_data));
1176
1177                 const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
1178                 {
1179                         VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,   // VkStructureType             sType;
1180                         DE_NULL,                                                                                // const void*                 pNext;
1181                         0u,                                                                                             // VkPipelineCacheCreateFlags  flags;
1182                         dataSize,                                                                               // deUintptr                   initialDataSize;
1183                         m_data,                                                                                 // const void*                 pInitialData;
1184                 };
1185                 m_newCache = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
1186         }
1187 }
1188
1189 PipelineFromCacheTestInstance::~PipelineFromCacheTestInstance (void)
1190 {
1191         delete[] m_data;
1192 }
1193
1194 void PipelineFromCacheTestInstance::preparePipelines (void)
1195 {
1196         preparePipelineWrapper(m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], *m_cache);
1197         preparePipelineWrapper(m_pipeline[PIPELINE_CACHE_NDX_CACHED], *m_newCache);
1198 }
1199
1200 class PipelineFromIncompleteCacheTest : public GraphicsCacheTest
1201 {
1202 public:
1203                                                         PipelineFromIncompleteCacheTest         (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param);
1204         virtual                                 ~PipelineFromIncompleteCacheTest        (void) {}
1205         virtual TestInstance*   createInstance                                          (Context& context) const;
1206 };
1207
1208 PipelineFromIncompleteCacheTest::PipelineFromIncompleteCacheTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param)
1209         : GraphicsCacheTest(testContext, name, description, param)
1210 {
1211 }
1212
1213 class PipelineFromIncompleteCacheTestInstance : public GraphicsCacheTestInstance
1214 {
1215 public:
1216                                                         PipelineFromIncompleteCacheTestInstance(Context& context, const CacheTestParam* param);
1217         virtual                                 ~PipelineFromIncompleteCacheTestInstance(void);
1218 protected:
1219         void                                    preparePipelines(void);
1220 protected:
1221         Move<VkPipelineCache>   m_newCache;
1222         deUint8*                                m_data;
1223 };
1224
1225 TestInstance* PipelineFromIncompleteCacheTest::createInstance (Context& context) const
1226 {
1227         return new PipelineFromIncompleteCacheTestInstance(context, &m_param);
1228 }
1229
1230 PipelineFromIncompleteCacheTestInstance::PipelineFromIncompleteCacheTestInstance (Context& context, const CacheTestParam* param)
1231         : GraphicsCacheTestInstance     (context, param)
1232         , m_data                                        (DE_NULL)
1233 {
1234         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1235         const VkDevice                  vkDevice        = m_context.getDevice();
1236
1237         // Create more pipeline caches
1238         {
1239                 size_t dataSize = 0u;
1240                 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, DE_NULL));
1241
1242                 if (dataSize == 0)
1243                         TCU_THROW(NotSupportedError, "Empty pipeline cache - unable to test");
1244
1245                 dataSize--;
1246
1247                 m_data = new deUint8[dataSize];
1248                 DE_ASSERT(m_data);
1249                 if (vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, (void*)m_data) != VK_INCOMPLETE)
1250                         TCU_THROW(TestError, "GetPipelineCacheData should return VK_INCOMPLETE state!");
1251
1252                 const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
1253                 {
1254                         VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,   // VkStructureType             sType;
1255                         DE_NULL,                                                                                // const void*                 pNext;
1256                         0u,                                                                                             // VkPipelineCacheCreateFlags  flags;
1257                         dataSize,                                                                               // deUintptr                   initialDataSize;
1258                         m_data,                                                                                 // const void*                 pInitialData;
1259                 };
1260                 m_newCache = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
1261         }
1262 }
1263
1264 PipelineFromIncompleteCacheTestInstance::~PipelineFromIncompleteCacheTestInstance (void)
1265 {
1266         delete[] m_data;
1267 }
1268
1269 void PipelineFromIncompleteCacheTestInstance::preparePipelines (void)
1270 {
1271         preparePipelineWrapper(m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], *m_cache);
1272         preparePipelineWrapper(m_pipeline[PIPELINE_CACHE_NDX_CACHED], *m_newCache);
1273 }
1274
1275 enum MergeCacheType
1276 {
1277         MERGE_CACHE_EMPTY = 0,
1278         MERGE_CACHE_FROM_DATA,
1279         MERGE_CACHE_HIT,
1280         MERGE_CACHE_MISS,
1281         MERGE_CACHE_MISS_AND_HIT,
1282         MERGE_CACHE_MERGED,
1283
1284         MERGE_CACHE_TYPE_LAST = MERGE_CACHE_MERGED
1285 };
1286
1287 std::string getMergeCacheTypeStr (MergeCacheType type)
1288 {
1289         switch (type)
1290         {
1291                 case MERGE_CACHE_EMPTY:
1292                         return "empty";
1293                 case MERGE_CACHE_FROM_DATA:
1294                         return "from_data";
1295                 case MERGE_CACHE_HIT:
1296                         return "hit";
1297                 case MERGE_CACHE_MISS_AND_HIT:
1298                         return "misshit";
1299                 case MERGE_CACHE_MISS:
1300                         return "miss";
1301                 case MERGE_CACHE_MERGED:
1302                         return "merged";
1303         }
1304         TCU_FAIL("unhandled merge cache type");
1305 }
1306
1307 std::string getMergeCacheTypesStr (const std::vector<MergeCacheType>& types)
1308 {
1309         std::string ret;
1310         for (size_t idx = 0; idx < types.size(); ++idx)
1311         {
1312                 if (ret.size())
1313                         ret += '_';
1314                 ret += getMergeCacheTypeStr(types[idx]);
1315         }
1316         return ret;
1317 }
1318
1319
1320 class MergeCacheTestParam
1321 {
1322 public:
1323         MergeCacheType                          destCacheType;
1324         std::vector<MergeCacheType> srcCacheTypes;
1325 };
1326
1327 class MergeCacheTest : public GraphicsCacheTest
1328 {
1329 public:
1330                                                                 MergeCacheTest  (tcu::TestContext&                      testContext,
1331                                                                                                  const std::string&                     name,
1332                                                                                                  const std::string&                     description,
1333                                                                                                  const CacheTestParam*          param,
1334                                                                                                  const MergeCacheTestParam* mergeCacheParam)
1335                                                                         : GraphicsCacheTest (testContext, name, description, param)
1336                                                                         , m_mergeCacheParam     (*mergeCacheParam)
1337                                                                         { }
1338         virtual                                         ~MergeCacheTest (void) { }
1339         virtual TestInstance*           createInstance  (Context& context) const;
1340 private:
1341         const MergeCacheTestParam       m_mergeCacheParam;
1342 };
1343
1344 class MergeCacheTestInstance : public GraphicsCacheTestInstance
1345 {
1346 public:
1347                                                         MergeCacheTestInstance  (Context&                                       context,
1348                                                                                                          const CacheTestParam*          param,
1349                                                                                                          const MergeCacheTestParam* mergeCacheParam);
1350 private:
1351         Move<VkPipelineCache>   createPipelineCache             (const DeviceInterface& vk, VkDevice device, MergeCacheType type);
1352
1353 protected:
1354         void                                    preparePipelines                (void);
1355
1356 protected:
1357         Move<VkPipelineCache>   m_cacheMerged;
1358 };
1359
1360 TestInstance* MergeCacheTest::createInstance (Context& context) const
1361 {
1362         return new MergeCacheTestInstance(context, &m_param, &m_mergeCacheParam);
1363 }
1364
1365 MergeCacheTestInstance::MergeCacheTestInstance (Context& context, const CacheTestParam* param, const MergeCacheTestParam* mergeCacheParam)
1366         : GraphicsCacheTestInstance (context, param)
1367 {
1368         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1369         const VkDevice                  vkDevice        = m_context.getDevice();
1370
1371         // Create a merge destination cache
1372         m_cacheMerged = createPipelineCache(vk, vkDevice, mergeCacheParam->destCacheType);
1373
1374         // Create more pipeline caches
1375         std::vector<VkPipelineCache>    sourceCaches    (mergeCacheParam->srcCacheTypes.size());
1376         typedef de::SharedPtr<Move<VkPipelineCache> > PipelineCachePtr;
1377         std::vector<PipelineCachePtr>   sourceCachePtrs (sourceCaches.size());
1378         {
1379                 for (size_t sourceIdx = 0; sourceIdx < mergeCacheParam->srcCacheTypes.size(); sourceIdx++)
1380                 {
1381                         // vk::Move is not copyable, so create it on heap and wrap into de::SharedPtr
1382                         PipelineCachePtr        pipelineCachePtr        (new Move<VkPipelineCache>());
1383                         *pipelineCachePtr = createPipelineCache(vk, vkDevice, mergeCacheParam->srcCacheTypes[sourceIdx]);
1384
1385                         sourceCachePtrs[sourceIdx]      = pipelineCachePtr;
1386                         sourceCaches[sourceIdx]         = **pipelineCachePtr;
1387                 }
1388         }
1389
1390         // Merge the caches
1391         VK_CHECK(vk.mergePipelineCaches(vkDevice, *m_cacheMerged, static_cast<deUint32>(sourceCaches.size()), &sourceCaches[0]));
1392 }
1393
1394 Move<VkPipelineCache> MergeCacheTestInstance::createPipelineCache (const DeviceInterface& vk, VkDevice device, MergeCacheType type)
1395 {
1396         VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
1397         {
1398                 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,   // VkStructureType             sType;
1399                 DE_NULL,                                                                                // const void*                 pNext;
1400                 0u,                                                                                             // VkPipelineCacheCreateFlags  flags;
1401                 0u,                                                                                             // deUintptr                   initialDataSize;
1402                 DE_NULL,                                                                                // const void*                 pInitialData;
1403         };
1404
1405         GraphicsPipelineWrapper localPipeline           (vk, device, m_param->getPipelineConstructionType());
1406         GraphicsPipelineWrapper localMissPipeline       (vk, device, m_param->getPipelineConstructionType());
1407
1408         switch (type)
1409         {
1410                 case MERGE_CACHE_EMPTY:
1411                 {
1412                         return vk::createPipelineCache(vk, device, &pipelineCacheCreateInfo);
1413                 }
1414                 case MERGE_CACHE_FROM_DATA:
1415                 {
1416                         // Create a cache with init data from m_cache
1417                         size_t  dataSize = 0u;
1418                         VK_CHECK(vk.getPipelineCacheData(device, *m_cache, (deUintptr*)&dataSize, DE_NULL));
1419
1420                         std::vector<deUint8> data(dataSize);
1421                         VK_CHECK(vk.getPipelineCacheData(device, *m_cache, (deUintptr*)&dataSize, &data[0]));
1422
1423                         pipelineCacheCreateInfo.initialDataSize = data.size();
1424                         pipelineCacheCreateInfo.pInitialData = &data[0];
1425                         return vk::createPipelineCache(vk, device, &pipelineCacheCreateInfo);
1426                 }
1427                 case MERGE_CACHE_HIT:
1428                 {
1429                         Move<VkPipelineCache> ret = createPipelineCache(vk, device, MERGE_CACHE_EMPTY);
1430
1431                         preparePipelineWrapper(localPipeline, *ret);
1432
1433                         return ret;
1434                 }
1435                 case MERGE_CACHE_MISS:
1436                 {
1437                         Move<VkPipelineCache> ret = createPipelineCache(vk, device, MERGE_CACHE_EMPTY);
1438
1439                         preparePipelineWrapper(localMissPipeline, *ret, true);
1440
1441                         return ret;
1442                 }
1443                 case MERGE_CACHE_MISS_AND_HIT:
1444                 {
1445                         Move<VkPipelineCache> ret = createPipelineCache(vk, device, MERGE_CACHE_EMPTY);
1446
1447                         preparePipelineWrapper(localPipeline, *ret);
1448                         preparePipelineWrapper(localMissPipeline, *ret, true);
1449
1450                         return ret;
1451                 }
1452                 case MERGE_CACHE_MERGED:
1453                 {
1454                         Move<VkPipelineCache>   cache1                  = createPipelineCache(vk, device, MERGE_CACHE_FROM_DATA);
1455                         Move<VkPipelineCache>   cache2                  = createPipelineCache(vk, device, MERGE_CACHE_HIT);
1456                         Move<VkPipelineCache>   cache3                  = createPipelineCache(vk, device, MERGE_CACHE_MISS);
1457
1458                         const VkPipelineCache   sourceCaches[]  =
1459                         {
1460                                 *cache1,
1461                                 *cache2,
1462                                 *cache3
1463                         };
1464
1465                         Move<VkPipelineCache>   ret                             = createPipelineCache(vk, device, MERGE_CACHE_EMPTY);
1466
1467                         // Merge the caches
1468                         VK_CHECK(vk.mergePipelineCaches(device, *ret, DE_LENGTH_OF_ARRAY(sourceCaches), sourceCaches));
1469
1470                         return ret;
1471                 }
1472         }
1473         TCU_FAIL("unhandled merge cache type");
1474 }
1475
1476 void MergeCacheTestInstance::preparePipelines(void)
1477 {
1478         preparePipelineWrapper(m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], *m_cache);
1479
1480         // Create pipeline from merged cache
1481         preparePipelineWrapper(m_pipeline[PIPELINE_CACHE_NDX_CACHED], *m_cacheMerged);
1482 }
1483
1484 class CacheHeaderTest : public GraphicsCacheTest
1485 {
1486 public:
1487                         CacheHeaderTest         (tcu::TestContext&              testContext,
1488                                                                  const std::string&             name,
1489                                                                  const std::string&             description,
1490                                                                  const CacheTestParam*  param)
1491                                                                 : GraphicsCacheTest(testContext, name, description, param)
1492         { }
1493         virtual ~CacheHeaderTest        (void) { }
1494         virtual TestInstance*           createInstance(Context& context) const;
1495 };
1496
1497 class CacheHeaderTestInstance : public GraphicsCacheTestInstance
1498 {
1499 public:
1500                                 CacheHeaderTestInstance         (Context& context, const CacheTestParam*  param);
1501         virtual         ~CacheHeaderTestInstance        (void);
1502 protected:
1503         deUint8*        m_data;
1504
1505         struct CacheHeader
1506         {
1507                 deUint32        HeaderLength;
1508                 deUint32        HeaderVersion;
1509                 deUint32        VendorID;
1510                 deUint32        DeviceID;
1511                 deUint8         PipelineCacheUUID[VK_UUID_SIZE];
1512         } m_header;
1513 };
1514
1515 TestInstance* CacheHeaderTest::createInstance (Context& context) const
1516 {
1517         return new CacheHeaderTestInstance(context, &m_param);
1518 }
1519
1520 CacheHeaderTestInstance::CacheHeaderTestInstance (Context& context, const CacheTestParam* param)
1521         : GraphicsCacheTestInstance     (context, param)
1522         , m_data                                        (DE_NULL)
1523 {
1524         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1525         const VkDevice                  vkDevice        = m_context.getDevice();
1526
1527         // Create more pipeline caches
1528         {
1529                 // Create a cache with init data from m_cache
1530                 size_t dataSize = 0u;
1531                 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, DE_NULL));
1532
1533                 if (dataSize < sizeof(m_header))
1534                         TCU_THROW(TestError, "Pipeline cache size is smaller than header size");
1535
1536                 m_data = new deUint8[dataSize];
1537                 DE_ASSERT(m_data);
1538                 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, (void*)m_data));
1539
1540                 deMemcpy(&m_header, m_data, sizeof(m_header));
1541
1542                 if (m_header.HeaderLength - VK_UUID_SIZE != 16)
1543                         TCU_THROW(TestError, "Invalid header size!");
1544
1545                 if (m_header.HeaderVersion != 1)
1546                         TCU_THROW(TestError, "Invalid header version!");
1547
1548                 if (m_header.VendorID != m_context.getDeviceProperties().vendorID)
1549                         TCU_THROW(TestError, "Invalid header vendor ID!");
1550
1551                 if (m_header.DeviceID != m_context.getDeviceProperties().deviceID)
1552                         TCU_THROW(TestError, "Invalid header device ID!");
1553
1554                 if (deMemCmp(&m_header.PipelineCacheUUID, &m_context.getDeviceProperties().pipelineCacheUUID, VK_UUID_SIZE) != 0)
1555                         TCU_THROW(TestError, "Invalid header pipeline cache UUID!");
1556         }
1557 }
1558
1559 CacheHeaderTestInstance::~CacheHeaderTestInstance (void)
1560 {
1561         delete[] m_data;
1562 }
1563
1564 class InvalidSizeTest : public GraphicsCacheTest
1565 {
1566 public:
1567                                                         InvalidSizeTest         (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param);
1568         virtual                                 ~InvalidSizeTest        (void) {}
1569         virtual TestInstance*   createInstance          (Context& context) const;
1570 };
1571
1572 InvalidSizeTest::InvalidSizeTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param)
1573         : GraphicsCacheTest(testContext, name, description, param)
1574 {
1575 }
1576
1577 class InvalidSizeTestInstance : public GraphicsCacheTestInstance
1578 {
1579 public:
1580                                                         InvalidSizeTestInstance         (Context& context, const CacheTestParam*  param);
1581         virtual                                 ~InvalidSizeTestInstance        (void);
1582 protected:
1583         deUint8*                                m_data;
1584         deUint8*                                m_zeroBlock;
1585 };
1586
1587 TestInstance* InvalidSizeTest::createInstance (Context& context) const
1588 {
1589         return new InvalidSizeTestInstance(context, &m_param);
1590 }
1591
1592 InvalidSizeTestInstance::InvalidSizeTestInstance (Context& context, const CacheTestParam* param)
1593         : GraphicsCacheTestInstance     (context, param)
1594         , m_data                                        (DE_NULL)
1595         , m_zeroBlock                           (DE_NULL)
1596 {
1597         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1598         const VkDevice                  vkDevice        = m_context.getDevice();
1599
1600         // Create more pipeline caches
1601         try
1602         {
1603                 // Create a cache with init data from m_cache
1604                 size_t dataSize                 = 0u;
1605                 size_t savedDataSize    = 0u;
1606                 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, DE_NULL));
1607                 savedDataSize = dataSize;
1608
1609                 // If the value of dataSize is less than the maximum size that can be retrieved by the pipeline cache,
1610                 // at most pDataSize bytes will be written to pData, and vkGetPipelineCacheData will return VK_INCOMPLETE.
1611                 dataSize--;
1612
1613                 m_data = new deUint8[savedDataSize];
1614                 deMemset(m_data, 0, savedDataSize);
1615                 DE_ASSERT(m_data);
1616                 if (vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, (void*)m_data) != VK_INCOMPLETE)
1617                         TCU_THROW(TestError, "GetPipelineCacheData should return VK_INCOMPLETE state!");
1618
1619                 delete[] m_data;
1620                 m_data = DE_NULL;
1621
1622                 // If the value of dataSize is less than what is necessary to store the header,
1623                 // nothing will be written to pData and zero will be written to dataSize.
1624                 dataSize = 16 + VK_UUID_SIZE - 1;
1625
1626                 m_data = new deUint8[savedDataSize];
1627                 deMemset(m_data, 0, savedDataSize);
1628                 DE_ASSERT(m_data);
1629                 if (vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, (void*)m_data) != VK_INCOMPLETE)
1630                         TCU_THROW(TestError, "GetPipelineCacheData should return VK_INCOMPLETE state!");
1631
1632                 m_zeroBlock = new deUint8[savedDataSize];
1633                 deMemset(m_zeroBlock, 0, savedDataSize);
1634                 if (deMemCmp(m_data, m_zeroBlock, savedDataSize) != 0 || dataSize != 0)
1635                         TCU_THROW(TestError, "Data needs to be empty and data size should be 0 when invalid size is passed to GetPipelineCacheData!");
1636         }
1637         catch (...)
1638         {
1639                 delete[] m_data;
1640                 delete[] m_zeroBlock;
1641                 throw;
1642         }
1643 }
1644
1645 InvalidSizeTestInstance::~InvalidSizeTestInstance (void)
1646 {
1647         delete[] m_data;
1648         delete[] m_zeroBlock;
1649 }
1650
1651 class ZeroSizeTest : public GraphicsCacheTest
1652 {
1653 public:
1654                                                         ZeroSizeTest    (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param);
1655         virtual                                 ~ZeroSizeTest   (void) {}
1656         virtual TestInstance*   createInstance  (Context& context) const;
1657 };
1658
1659 ZeroSizeTest::ZeroSizeTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param)
1660         : GraphicsCacheTest(testContext, name, description, param)
1661 {
1662 }
1663
1664 class ZeroSizeTestInstance : public GraphicsCacheTestInstance
1665 {
1666 public:
1667                                                         ZeroSizeTestInstance    (Context& context, const CacheTestParam* param);
1668         virtual                                 ~ZeroSizeTestInstance   (void);
1669 protected:
1670         deUint8*                                m_data;
1671         deUint8*                                m_zeroBlock;
1672 };
1673
1674 TestInstance* ZeroSizeTest::createInstance (Context& context) const
1675 {
1676         return new ZeroSizeTestInstance(context, &m_param);
1677 }
1678
1679 ZeroSizeTestInstance::ZeroSizeTestInstance (Context& context, const CacheTestParam* param)
1680         : GraphicsCacheTestInstance     (context, param)
1681         , m_data                                        (DE_NULL)
1682         , m_zeroBlock                           (DE_NULL)
1683 {
1684         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1685         const VkDevice                  vkDevice        = m_context.getDevice();
1686
1687         // Create more pipeline caches
1688         try
1689         {
1690                 // Create a cache with init data from m_cache
1691                 size_t dataSize = 0u;
1692
1693                 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, DE_NULL));
1694
1695                 m_data = new deUint8[dataSize];
1696                 deMemset(m_data, 0, dataSize);
1697                 DE_ASSERT(m_data);
1698
1699                 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, (void*)m_data));
1700
1701                 {
1702                         // Create a cache with initialDataSize = 0 & pInitialData != NULL
1703                         const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
1704                         {
1705                                 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,   // VkStructureType             sType;
1706                                 DE_NULL,                                                                                // const void*                 pNext;
1707                                 0u,                                                                                             // VkPipelineCacheCreateFlags  flags;
1708                                 0u,                                                                                             // deUintptr                   initialDataSize;
1709                                 m_data,                                                                                 // const void*                 pInitialData;
1710                         };
1711
1712                         const Unique<VkPipelineCache>   pipelineCache                   (createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo));
1713                 }
1714         }
1715         catch (...)
1716         {
1717                 delete[] m_data;
1718                 delete[] m_zeroBlock;
1719                 throw;
1720         }
1721 }
1722
1723 ZeroSizeTestInstance::~ZeroSizeTestInstance (void)
1724 {
1725         delete[] m_data;
1726         delete[] m_zeroBlock;
1727 }
1728
1729 class InvalidBlobTest : public GraphicsCacheTest
1730 {
1731 public:
1732                                                         InvalidBlobTest         (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param);
1733         virtual                                 ~InvalidBlobTest        (void) {}
1734         virtual TestInstance*   createInstance          (Context& context) const;
1735 };
1736
1737 InvalidBlobTest::InvalidBlobTest (tcu::TestContext& testContext, const std::string& name, const std::string& description, const CacheTestParam* param)
1738         : GraphicsCacheTest(testContext, name, description, param)
1739 {
1740 }
1741
1742 class InvalidBlobTestInstance : public GraphicsCacheTestInstance
1743 {
1744 public:
1745                                                         InvalidBlobTestInstance         (Context& context, const CacheTestParam* param);
1746         virtual                                 ~InvalidBlobTestInstance        (void);
1747 protected:
1748         deUint8*                                m_data;
1749         deUint8*                                m_zeroBlock;
1750 };
1751
1752 TestInstance* InvalidBlobTest::createInstance (Context& context) const
1753 {
1754         return new InvalidBlobTestInstance(context, &m_param);
1755 }
1756
1757 InvalidBlobTestInstance::InvalidBlobTestInstance (Context& context, const CacheTestParam* param)
1758         : GraphicsCacheTestInstance     (context, param)
1759         , m_data                                        (DE_NULL)
1760         , m_zeroBlock                           (DE_NULL)
1761 {
1762         const DeviceInterface&  vk                      = m_context.getDeviceInterface();
1763         const VkDevice                  vkDevice        = m_context.getDevice();
1764
1765         // Create more pipeline caches
1766         try
1767         {
1768                 // Create a cache with init data from m_cache
1769                 size_t dataSize = 0u;
1770
1771                 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, DE_NULL));
1772
1773                 m_data = new deUint8[dataSize];
1774                 deMemset(m_data, 0, dataSize);
1775                 DE_ASSERT(m_data);
1776
1777                 VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, (void*)m_data));
1778
1779                 const struct
1780                 {
1781                         deUint32        offset;
1782                         std::string     name;
1783                 } headerLayout[] =
1784                 {
1785                         { 4u,   "pipeline cache header version" },
1786                         { 8u,   "vendor ID"                                             },
1787                         { 12u,  "device ID"                                             },
1788                         { 16u,  "pipeline cache ID"                             }
1789                 };
1790
1791                 for (deUint32 i = 0u; i < DE_LENGTH_OF_ARRAY(headerLayout); i++)
1792                 {
1793                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Creating pipeline cache using previously retrieved data with invalid " << headerLayout[i].name << tcu::TestLog::EndMessage;
1794
1795                         m_data[headerLayout[i].offset] = (deUint8)(m_data[headerLayout[i].offset] + 13u);       // Add arbitrary number to create an invalid value
1796
1797                         const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
1798                         {
1799                                 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,   // VkStructureType             sType;
1800                                 DE_NULL,                                                                                // const void*                 pNext;
1801                                 0u,                                                                                             // VkPipelineCacheCreateFlags  flags;
1802                                 dataSize,                                                                               // deUintptr                   initialDataSize;
1803                                 m_data,                                                                                 // const void*                 pInitialData;
1804                         };
1805
1806                         const Unique<VkPipelineCache>   pipelineCache                   (createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo));
1807
1808                         m_data[headerLayout[i].offset] = (deUint8)(m_data[headerLayout[i].offset] - 13u);       // Return to original value
1809                 }
1810         }
1811         catch (...)
1812         {
1813                 delete[] m_data;
1814                 delete[] m_zeroBlock;
1815                 throw;
1816         }
1817 }
1818
1819 InvalidBlobTestInstance::~InvalidBlobTestInstance (void)
1820 {
1821         delete[] m_data;
1822         delete[] m_zeroBlock;
1823 }
1824 } // anonymous
1825
1826 tcu::TestCaseGroup* createCacheTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
1827 {
1828         de::MovePtr<tcu::TestCaseGroup> cacheTests (new tcu::TestCaseGroup(testCtx, "cache", "pipeline cache tests"));
1829
1830         const VkShaderStageFlags vertFragStages                 = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
1831         const VkShaderStageFlags vertGeomFragStages             = vertFragStages | VK_SHADER_STAGE_GEOMETRY_BIT;
1832         const VkShaderStageFlags vertTesFragStages              = vertFragStages | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
1833
1834         // Graphics Pipeline Tests
1835         {
1836                 de::MovePtr<tcu::TestCaseGroup> graphicsTests (new tcu::TestCaseGroup(testCtx, "graphics_tests", "Test pipeline cache with graphics pipeline."));
1837
1838                 const CacheTestParam testParams[] =
1839                 {
1840                         CacheTestParam(pipelineConstructionType, vertFragStages,                false),
1841                         CacheTestParam(pipelineConstructionType, vertGeomFragStages,    false),
1842                         CacheTestParam(pipelineConstructionType, vertTesFragStages,             false),
1843                         CacheTestParam(pipelineConstructionType, vertFragStages,                false, VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT),
1844                         CacheTestParam(pipelineConstructionType, vertGeomFragStages,    false, VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT),
1845                         CacheTestParam(pipelineConstructionType, vertTesFragStages,             false, VK_PIPELINE_CACHE_CREATE_EXTERNALLY_SYNCHRONIZED_BIT),
1846                 };
1847
1848                 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1849                         graphicsTests->addChild(newTestCase<GraphicsCacheTest>(testCtx, &testParams[i]));
1850
1851                 cacheTests->addChild(graphicsTests.release());
1852         }
1853
1854         // Graphics Pipeline Tests
1855         {
1856                 de::MovePtr<tcu::TestCaseGroup> graphicsTests(new tcu::TestCaseGroup(testCtx, "pipeline_from_get_data", "Test pipeline cache with graphics pipeline."));
1857
1858                 const CacheTestParam testParams[] =
1859                 {
1860                         CacheTestParam(pipelineConstructionType, vertFragStages,                false),
1861                         CacheTestParam(pipelineConstructionType, vertGeomFragStages,    false),
1862                         CacheTestParam(pipelineConstructionType, vertTesFragStages,             false),
1863                 };
1864
1865                 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1866                         graphicsTests->addChild(newTestCase<PipelineFromCacheTest>(testCtx, &testParams[i]));
1867
1868                 cacheTests->addChild(graphicsTests.release());
1869         }
1870
1871         // Graphics Pipeline Tests
1872         {
1873                 de::MovePtr<tcu::TestCaseGroup> graphicsTests(new tcu::TestCaseGroup(testCtx, "pipeline_from_incomplete_get_data", "Test pipeline cache with graphics pipeline."));
1874
1875                 const CacheTestParam testParams[] =
1876                 {
1877                         CacheTestParam(pipelineConstructionType, vertFragStages,                false),
1878                         CacheTestParam(pipelineConstructionType, vertGeomFragStages,    false),
1879                         CacheTestParam(pipelineConstructionType, vertTesFragStages,             false),
1880                 };
1881
1882                 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1883                         graphicsTests->addChild(newTestCase<PipelineFromIncompleteCacheTest>(testCtx, &testParams[i]));
1884
1885                 cacheTests->addChild(graphicsTests.release());
1886         }
1887
1888         // Compute Pipeline Tests - don't repeat those tests for graphics pipeline library
1889         if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1890         {
1891                 de::MovePtr<tcu::TestCaseGroup> computeTests (new tcu::TestCaseGroup(testCtx, "compute_tests", "Test pipeline cache with compute pipeline."));
1892
1893                 const CacheTestParam testParams[] =
1894                 {
1895                         CacheTestParam(pipelineConstructionType, VK_SHADER_STAGE_COMPUTE_BIT, false),
1896                 };
1897
1898                 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1899                         computeTests->addChild(newTestCase<ComputeCacheTest>(testCtx, &testParams[i]));
1900
1901                 cacheTests->addChild(computeTests.release());
1902         }
1903
1904         // Merge cache Tests
1905         {
1906                 de::MovePtr<tcu::TestCaseGroup> mergeTests (new tcu::TestCaseGroup(testCtx, "merge", "Cache merging tests"));
1907
1908                 const CacheTestParam testParams[] =
1909                 {
1910                         CacheTestParam(pipelineConstructionType, vertFragStages,                true),
1911                         CacheTestParam(pipelineConstructionType, vertGeomFragStages,    true),
1912                         CacheTestParam(pipelineConstructionType, vertTesFragStages,             true),
1913                 };
1914
1915                 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1916                 {
1917
1918                         de::MovePtr<tcu::TestCaseGroup> mergeStagesTests(new tcu::TestCaseGroup(testCtx, testParams[i].generateTestName().c_str(), testParams[i].generateTestDescription().c_str()));
1919
1920                         for (deUint32 destTypeIdx = 0u; destTypeIdx <= MERGE_CACHE_TYPE_LAST; destTypeIdx++)
1921                         for (deUint32 srcType1Idx = 0u; srcType1Idx <= MERGE_CACHE_TYPE_LAST; srcType1Idx++)
1922                         {
1923
1924                                 MergeCacheTestParam cacheTestParam;
1925                                 cacheTestParam.destCacheType = MergeCacheType(destTypeIdx);
1926                                 cacheTestParam.srcCacheTypes.push_back(MergeCacheType(srcType1Idx));
1927
1928                                 // merge with one cache
1929                                 {
1930                                         std::string testName = "src_" + getMergeCacheTypesStr(cacheTestParam.srcCacheTypes) + "_dst_" + getMergeCacheTypeStr(cacheTestParam.destCacheType);
1931                                         mergeStagesTests->addChild(new MergeCacheTest(testCtx,
1932                                                                                                                         testName.c_str(),
1933                                                                                                                         "Merge the caches test.",
1934                                                                                                                         &testParams[i],
1935                                                                                                                         &cacheTestParam));
1936                                 }
1937
1938                                 // merge with two caches
1939                                 for (deUint32 srcType2Idx = 0u; srcType2Idx <= MERGE_CACHE_TYPE_LAST; srcType2Idx++)
1940                                 {
1941                                         MergeCacheTestParam cacheTestParamTwoCaches = cacheTestParam;
1942
1943                                         cacheTestParamTwoCaches.srcCacheTypes.push_back(MergeCacheType(srcType2Idx));
1944
1945                                         std::string testName = "src_" + getMergeCacheTypesStr(cacheTestParamTwoCaches.srcCacheTypes) + "_dst_" + getMergeCacheTypeStr(cacheTestParamTwoCaches.destCacheType);
1946                                         mergeStagesTests->addChild(new MergeCacheTest(testCtx,
1947                                                                                                                    testName.c_str(),
1948                                                                                                                    "Merge the caches test.",
1949                                                                                                                    &testParams[i],
1950                                                                                                                    &cacheTestParamTwoCaches));
1951                                 }
1952                         }
1953                         mergeTests->addChild(mergeStagesTests.release());
1954                 }
1955                 cacheTests->addChild(mergeTests.release());
1956         }
1957
1958         // Misc Tests
1959         {
1960                 de::MovePtr<tcu::TestCaseGroup> miscTests(new tcu::TestCaseGroup(testCtx, "misc_tests", "Misc tests that can not be categorized to other group."));
1961
1962                 const CacheTestParam testParam(pipelineConstructionType, vertFragStages, false);
1963
1964                 miscTests->addChild(new CacheHeaderTest(testCtx,
1965                                                                                            "cache_header_test",
1966                                                                                            "Cache header test.",
1967                                                                                            &testParam));
1968
1969                 miscTests->addChild(new InvalidSizeTest(testCtx,
1970                                                                                                 "invalid_size_test",
1971                                                                                                 "Invalid size test.",
1972                                                                                                 &testParam));
1973
1974                 miscTests->addChild(new ZeroSizeTest(testCtx,
1975                                                                                          "zero_size_test",
1976                                                                                          "Zero size test.",
1977                                                                                          &testParam));
1978
1979                 miscTests->addChild(new InvalidBlobTest(testCtx,
1980                                                                                                 "invalid_blob_test",
1981                                                                                                 "Invalid cache blob test.",
1982                                                                                                 &testParam));
1983
1984                 cacheTests->addChild(miscTests.release());
1985         }
1986
1987         return cacheTests.release();
1988 }
1989
1990 } // pipeline
1991
1992 } // vkt