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 "tcuImageCompare.hpp"
39#include "deUniquePtr.hpp"
40#include "deMemory.h"
41#include "vkTypeUtil.hpp"
42
43#include <sstream>
44#include <vector>
45
46namespace vkt
47{
48namespace pipeline
49{
50
51using namespace vk;
52
53namespace
54{
55enum
56{
57	VK_MAX_SHADER_STAGES = 6,
58};
59
60// helper functions
61
62std::string getShaderFlagStr (const VkShaderStageFlagBits shader,
63							  bool                        isDescription)
64{
65	std::ostringstream desc;
66	switch(shader)
67	{
68		case VK_SHADER_STAGE_VERTEX_BIT:
69		{
70			desc << ((isDescription) ? "vertex stage" : "vertex_stage");
71			break;
72		}
73		case VK_SHADER_STAGE_FRAGMENT_BIT:
74		{
75			desc << ((isDescription) ? "fragment stage" : "fragment_stage");
76			break;
77		}
78		case VK_SHADER_STAGE_GEOMETRY_BIT:
79		{
80			desc << ((isDescription) ? "geometry stage" : "geometry_stage");
81			break;
82		}
83		case VK_SHADER_STAGE_COMPUTE_BIT:
84		{
85			desc << ((isDescription) ? "compute stage" : "compute_stage");
86			break;
87		}
88		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
89		{
90			desc << ((isDescription) ? "tessellation control stage" : "tessellation_control_stage");
91			break;
92		}
93		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
94		{
95			desc << ((isDescription) ? "tessellation evaluation stage" : "tessellation_evaluation_stage");
96			break;
97		}
98	  default:
99		desc << "unknown shader stage!";
100		DE_FATAL("Unknown shader Stage!");
101		break;
102	};
103
104	return desc.str();
105}
106
107// helper classes
108class CacheTestParam
109{
110public:
111								CacheTestParam          (const VkShaderStageFlagBits* shaders,
112														 deUint32                     count);
113	virtual 					~CacheTestParam         (void);
114	virtual const std::string   generateTestName        (void)          const;
115	virtual const std::string   generateTestDescription (void)          const;
116	VkShaderStageFlagBits       getShaderFlag           (deUint32 ndx)  const   { return m_shaders[ndx]; }
117	deUint32                    getShaderCount          (void)          const   { return (deUint32)m_shaderCount; }
118protected:
119	VkShaderStageFlagBits       m_shaders[VK_MAX_SHADER_STAGES];
120	size_t                      m_shaderCount;
121};
122
123CacheTestParam::CacheTestParam (const VkShaderStageFlagBits* shaders, deUint32 count)
124{
125	DE_ASSERT(count <= VK_MAX_SHADER_STAGES);
126	for (deUint32 ndx = 0; ndx < count; ndx++)
127		m_shaders[ndx] = shaders[ndx];
128	m_shaderCount = count;
129}
130
131CacheTestParam::~CacheTestParam (void)
132{
133}
134
135const std::string CacheTestParam::generateTestName (void) const
136{
137	std::string result(getShaderFlagStr(m_shaders[0], false));
138
139	for(deUint32 ndx = 1; ndx < m_shaderCount; ndx++)
140		result += '_' + getShaderFlagStr(m_shaders[ndx], false) ;
141
142	return result;
143}
144
145const std::string CacheTestParam::generateTestDescription (void) const
146{
147	std::string result("Create pipeline cache with " + getShaderFlagStr(m_shaders[0], true));
148
149	for(deUint32 ndx = 1; ndx < m_shaderCount; ndx++)
150		result += ' ' + getShaderFlagStr(m_shaders[ndx], true);
151
152	return result;
153}
154
155class SimpleGraphicsPipelineBuilder
156{
157public:
158					 SimpleGraphicsPipelineBuilder  (Context&              context);
159					 ~SimpleGraphicsPipelineBuilder (void) { }
160	void             bindShaderStage                (VkShaderStageFlagBits stage,
161													 const char*           sourceName,
162													 const char*           entryName);
163	void             enableTessellationStage        (deUint32              patchControlPoints);
164	Move<VkPipeline> buildPipeline                  (tcu::UVec2            renderSize,
165													 VkRenderPass          renderPass,
166													 VkPipelineCache       cache);
167protected:
168	Context&                            m_context;
169
170	Move<VkShaderModule>                m_shaderModules[VK_MAX_SHADER_STAGES];
171	deUint32                            m_shaderStageCount;
172	VkPipelineShaderStageCreateInfo     m_shaderStageInfo[VK_MAX_SHADER_STAGES];
173
174	deUint32                            m_patchControlPoints;
175
176	Move<VkPipelineLayout>              m_pipelineLayout;
177	Move<VkPipeline>                    m_graphicsPipelines;
178
179};
180
181SimpleGraphicsPipelineBuilder::SimpleGraphicsPipelineBuilder (Context& context)
182	: m_context(context)
183{
184	m_patchControlPoints = 0;
185	m_shaderStageCount   = 0;
186}
187
188void SimpleGraphicsPipelineBuilder::bindShaderStage (VkShaderStageFlagBits stage,
189													 const char*           sourceName,
190													 const char*           entryName)
191{
192	const DeviceInterface&  vk        = m_context.getDeviceInterface();
193	const VkDevice          vkDevice  = m_context.getDevice();
194
195	// Create shader module
196	deUint32*               code     = (deUint32*)m_context.getBinaryCollection().get(sourceName).getBinary();
197	deUint32                codeSize  = (deUint32)m_context.getBinaryCollection().get(sourceName).getSize();
198
199	const VkShaderModuleCreateInfo moduleCreateInfo =
200	{
201		VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,                // VkStructureType             sType;
202		DE_NULL,                                                    // const void*                 pNext;
203		0u,                                                         // VkShaderModuleCreateFlags   flags;
204		codeSize,                                                   // deUintptr                   codeSize;
205		code,                                                       // const deUint32*             pCode;
206	};
207
208	m_shaderModules[m_shaderStageCount] = createShaderModule(vk, vkDevice, &moduleCreateInfo);
209
210	// Prepare shader stage info
211	m_shaderStageInfo[m_shaderStageCount].sType               = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
212	m_shaderStageInfo[m_shaderStageCount].pNext               = DE_NULL;
213	m_shaderStageInfo[m_shaderStageCount].flags               = 0u;
214	m_shaderStageInfo[m_shaderStageCount].stage               = stage;
215	m_shaderStageInfo[m_shaderStageCount].module              = *m_shaderModules[m_shaderStageCount];
216	m_shaderStageInfo[m_shaderStageCount].pName               = entryName;
217	m_shaderStageInfo[m_shaderStageCount].pSpecializationInfo = DE_NULL;
218
219	m_shaderStageCount++;
220}
221
222Move<VkPipeline> SimpleGraphicsPipelineBuilder::buildPipeline (tcu::UVec2 renderSize, VkRenderPass renderPass, VkPipelineCache cache)
223{
224	const DeviceInterface&      vk                  = m_context.getDeviceInterface();
225	const VkDevice              vkDevice            = m_context.getDevice();
226
227	// Create pipeline layout
228	{
229		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
230		{
231			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,      // VkStructureType                  sType;
232			DE_NULL,                                            // const void*                      pNext;
233			0u,                                                 // VkPipelineLayoutCreateFlags      flags;
234			0u,                                                 // deUint32                         setLayoutCount;
235			DE_NULL,                                            // const VkDescriptorSetLayout*     pSetLayouts;
236			0u,                                                 // deUint32                         pushConstantRangeCount;
237			DE_NULL                                             // const VkPushConstantRange*       pPushConstantRanges;
238		};
239
240		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
241	}
242
243	// Create pipeline
244	const VkVertexInputBindingDescription vertexInputBindingDescription =
245	{
246		0u,                                 // deUint32                 binding;
247		sizeof(Vertex4RGBA),                // deUint32                 strideInBytes;
248		VK_VERTEX_INPUT_RATE_VERTEX,        // VkVertexInputRate        inputRate;
249	};
250
251	const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
252	{
253		{
254			0u,                                 // deUint32 location;
255			0u,                                 // deUint32 binding;
256			VK_FORMAT_R32G32B32A32_SFLOAT,      // VkFormat format;
257			0u                                  // deUint32 offsetInBytes;
258		},
259		{
260			1u,                                 // deUint32 location;
261			0u,                                 // deUint32 binding;
262			VK_FORMAT_R32G32B32A32_SFLOAT,      // VkFormat format;
263			DE_OFFSET_OF(Vertex4RGBA, color),   // deUint32 offsetInBytes;
264		}
265	};
266
267	const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
268	{
269		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,      // VkStructureType                          sType;
270		DE_NULL,                                                        // const void*                              pNext;
271		0u,                                                             // VkPipelineVertexInputStateCreateFlags    flags;
272		1u,                                                             // deUint32                                 vertexBindingDescriptionCount;
273		&vertexInputBindingDescription,                                 // const VkVertexInputBindingDescription*   pVertexBindingDescriptions;
274		2u,                                                             // deUint32                                 vertexAttributeDescriptionCount;
275		vertexInputAttributeDescriptions,                               // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
276	};
277
278	const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
279	{
280		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,    // VkStructureType                          sType;
281		DE_NULL,                                                        // const void*                              pNext;
282		0u,                                                             // VkPipelineInputAssemblyStateCreateFlags  flags;
283		(m_patchControlPoints == 0 ? VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
284								   : VK_PRIMITIVE_TOPOLOGY_PATCH_LIST), // VkPrimitiveTopology                      topology;
285		VK_FALSE,                                                       // VkBool32                                 primitiveRestartEnable;
286	};
287
288	const VkViewport viewport =
289	{
290		0.0f,                       // float    originX;
291		0.0f,                       // float    originY;
292		(float)renderSize.x(),      // float    width;
293		(float)renderSize.y(),      // float    height;
294		0.0f,                       // float    minDepth;
295		1.0f                        // float    maxDepth;
296	};
297	const VkRect2D scissor =
298	{
299		{ 0, 0 },                                                       // VkOffset2D  offset;
300		{ renderSize.x(), renderSize.y() }                              // VkExtent2D  extent;
301	};
302	const VkPipelineViewportStateCreateInfo viewportStateParams =
303	{
304		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,          // VkStructureType                      sType;
305		DE_NULL,                                                        // const void*                          pNext;
306		0u,                                                             // VkPipelineViewportStateCreateFlags   flags;
307		1u,                                                             // deUint32                             viewportCount;
308		&viewport,                                                      // const VkViewport*                    pViewports;
309		1u,                                                             // deUint32                             scissorCount;
310		&scissor                                                        // const VkRect2D*                      pScissors;
311	};
312
313	const VkPipelineRasterizationStateCreateInfo rasterStateParams =
314	{
315		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,     // VkStructureType                          sType;
316		DE_NULL,                                                        // const void*                              pNext;
317		0u,                                                             // VkPipelineRasterizationStateCreateFlags  flags;
318		VK_FALSE,                                                       // VkBool32                                 depthClampEnable;
319		VK_FALSE,                                                       // VkBool32                                 rasterizerDiscardEnable;
320		VK_POLYGON_MODE_FILL,                                           // VkPolygonMode                            polygonMode;
321		VK_CULL_MODE_NONE,                                              // VkCullModeFlags                          cullMode;
322		VK_FRONT_FACE_COUNTER_CLOCKWISE,                                // VkFrontFace                              frontFace;
323		VK_FALSE,                                                       // VkBool32                                 depthBiasEnable;
324		0.0f,                                                           // float                                    depthBiasConstantFactor;
325		0.0f,                                                           // float                                    depthBiasClamp;
326		0.0f,                                                           // float                                    depthBiasSlopeFactor;
327		1.0f,                                                           // float                                    lineWidth;
328	};
329
330	const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
331	{
332		VK_FALSE,                                                                   // VkBool32                 blendEnable;
333		VK_BLEND_FACTOR_ONE,                                                        // VkBlendFactor            srcColorBlendFactor;
334		VK_BLEND_FACTOR_ZERO,                                                       // VkBlendFactor            dstColorBlendFactor;
335		VK_BLEND_OP_ADD,                                                            // VkBlendOp                colorBlendOp;
336		VK_BLEND_FACTOR_ONE,                                                        // VkBlendFactor            srcAlphaBlendFactor;
337		VK_BLEND_FACTOR_ZERO,                                                       // VkBlendFactor            dstAlphaBlendFactor;
338		VK_BLEND_OP_ADD,                                                            // VkBlendOp                alphaBlendOp;
339		VK_COLOR_COMPONENT_R_BIT |
340		VK_COLOR_COMPONENT_G_BIT |
341		VK_COLOR_COMPONENT_B_BIT |
342		VK_COLOR_COMPONENT_A_BIT                                                    // VkColorComponentFlags    colorWriteMask;
343	};
344
345	const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
346	{
347		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,   // VkStructureType                              sType;
348		DE_NULL,                                                    // const void*                                  pNext;
349		0u,                                                         // VkPipelineColorBlendStateCreateFlags         flags;
350		VK_FALSE,                                                   // VkBool32                                     logicOpEnable;
351		VK_LOGIC_OP_COPY,                                           // VkLogicOp                                    logicOp;
352		1u,                                                         // deUint32                                     attachmentCount;
353		&colorBlendAttachmentState,                                 // const VkPipelineColorBlendAttachmentState*   pAttachments;
354		{ 0.0f, 0.0f, 0.0f, 0.0f },                                 // float                                        blendConst[4];
355	};
356
357	const VkPipelineMultisampleStateCreateInfo  multisampleStateParams  =
358	{
359		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,   // VkStructureType                          sType;
360		DE_NULL,                                                    // const void*                              pNext;
361		0u,                                                         // VkPipelineMultisampleStateCreateFlags    flags;
362		VK_SAMPLE_COUNT_1_BIT,                                      // VkSampleCountFlagBits                    rasterizationSamples;
363		VK_FALSE,                                                   // VkBool32                                 sampleShadingEnable;
364		0.0f,                                                       // float                                    minSampleShading;
365		DE_NULL,                                                    // const VkSampleMask*                      pSampleMask;
366		VK_FALSE,                                                   // VkBool32                                 alphaToCoverageEnable;
367		VK_FALSE,                                                   // VkBool32                                 alphaToOneEnable;
368	};
369
370	VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
371	{
372		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType                          sType;
373		DE_NULL,                                                    // const void*                              pNext;
374		0u,                                                         // VkPipelineDepthStencilStateCreateFlags   flags;
375		VK_TRUE,                                                    // VkBool32                                 depthTestEnable;
376		VK_TRUE,                                                    // VkBool32                                 depthWriteEnable;
377		VK_COMPARE_OP_LESS_OR_EQUAL,                                // VkCompareOp                              depthCompareOp;
378		VK_FALSE,                                                   // VkBool32                                 depthBoundsTestEnable;
379		VK_FALSE,                                                   // VkBool32                                 stencilTestEnable;
380		// VkStencilOpState front;
381		{
382			VK_STENCIL_OP_KEEP,     // VkStencilOp  failOp;
383			VK_STENCIL_OP_KEEP,     // VkStencilOp  passOp;
384			VK_STENCIL_OP_KEEP,     // VkStencilOp  depthFailOp;
385			VK_COMPARE_OP_NEVER,    // VkCompareOp  compareOp;
386			0u,                     // deUint32     compareMask;
387			0u,                     // deUint32     writeMask;
388			0u,                     // deUint32     reference;
389		},
390		// VkStencilOpState back;
391		{
392			VK_STENCIL_OP_KEEP,     // VkStencilOp  failOp;
393			VK_STENCIL_OP_KEEP,     // VkStencilOp  passOp;
394			VK_STENCIL_OP_KEEP,     // VkStencilOp  depthFailOp;
395			VK_COMPARE_OP_NEVER,    // VkCompareOp  compareOp;
396			0u,                     // deUint32     compareMask;
397			0u,                     // deUint32     writeMask;
398			0u,                     // deUint32     reference;
399		},
400		0.0f,                                                      // float                                    minDepthBounds;
401		1.0f,                                                      // float                                    maxDepthBounds;
402	};
403
404	const VkPipelineTessellationStateCreateInfo tessStateCreateInfo =
405	{
406		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,  // VkStructureType                          sType;
407		DE_NULL,                                                    // const void*                              pNext;
408		0u,                                                         // VkPipelineTesselationStateCreateFlags    flags;
409		m_patchControlPoints,                                       // deUint32                                 patchControlPoints;
410	};
411	const VkPipelineTessellationStateCreateInfo* pTessCreateInfo = (m_patchControlPoints > 0)
412																  ? &tessStateCreateInfo
413																  : DE_NULL;
414
415	const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
416	{
417		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,    // VkStructureType                                  sType;
418		DE_NULL,                                            // const void*                                      pNext;
419		0u,                                                 // VkPipelineCreateFlags                            flags;
420		m_shaderStageCount,                                 // deUint32                                         stageCount;
421		m_shaderStageInfo,                                  // const VkPipelineShaderStageCreateInfo*           pStages;
422		&vertexInputStateParams,                            // const VkPipelineVertexInputStateCreateInfo*      pVertexInputState;
423		&inputAssemblyStateParams,                          // const VkPipelineInputAssemblyStateCreateInfo*    pInputAssemblyState;
424		pTessCreateInfo,                                    // const VkPipelineTessellationStateCreateInfo*     pTessellationState;
425		&viewportStateParams,                               // const VkPipelineViewportStateCreateInfo*         pViewportState;
426		&rasterStateParams,                                 // const VkPipelineRasterizationStateCreateInfo*    pRasterState;
427		&multisampleStateParams,                            // const VkPipelineMultisampleStateCreateInfo*      pMultisampleState;
428		&depthStencilStateParams,                           // const VkPipelineDepthStencilStateCreateInfo*     pDepthStencilState;
429		&colorBlendStateParams,                             // const VkPipelineColorBlendStateCreateInfo*       pColorBlendState;
430		(const VkPipelineDynamicStateCreateInfo*)DE_NULL,   // const VkPipelineDynamicStateCreateInfo*          pDynamicState;
431		*m_pipelineLayout,                                  // VkPipelineLayout                                 layout;
432		renderPass,                                         // VkRenderPass                                     renderPass;
433		0u,                                                 // deUint32                                         subpass;
434		0u,                                                 // VkPipeline                                       basePipelineHandle;
435		0,                                                  // deInt32                                          basePipelineIndex;
436	};
437
438	return createGraphicsPipeline(vk, vkDevice, cache, &graphicsPipelineParams);
439}
440
441void SimpleGraphicsPipelineBuilder::enableTessellationStage (deUint32 patchControlPoints)
442{
443	m_patchControlPoints = patchControlPoints;
444}
445
446template <class Test>
447vkt::TestCase* newTestCase (tcu::TestContext&     testContext,
448						    const CacheTestParam* testParam)
449{
450	return new Test(testContext,
451					testParam->generateTestName().c_str(),
452					testParam->generateTestDescription().c_str(),
453					testParam);
454}
455
456Move<VkBuffer> createBufferAndBindMemory (Context& context, VkDeviceSize size, VkBufferUsageFlags usage, de::MovePtr<Allocation>* pAlloc)
457{
458	const DeviceInterface&  vk               = context.getDeviceInterface();
459	const VkDevice          vkDevice         = context.getDevice();
460	const deUint32          queueFamilyIndex = context.getUniversalQueueFamilyIndex();
461	SimpleAllocator*        memAlloc         = new SimpleAllocator(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
462
463	const VkBufferCreateInfo vertexBufferParams =
464	{
465		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,       // VkStructureType      sType;
466		DE_NULL,                                    // const void*          pNext;
467		0u,                                         // VkBufferCreateFlags  flags;
468		size,                                       // VkDeviceSize         size;
469		usage,                                      // VkBufferUsageFlags   usage;
470		VK_SHARING_MODE_EXCLUSIVE,                  // VkSharingMode        sharingMode;
471		1u,                                         // deUint32             queueFamilyCount;
472		&queueFamilyIndex                           // const deUint32*      pQueueFamilyIndices;
473	};
474
475	Move<VkBuffer> vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
476
477	DE_ASSERT(pAlloc);
478	*pAlloc = memAlloc->allocate(getBufferMemoryRequirements(vk, vkDevice, *vertexBuffer), MemoryRequirement::HostVisible);
479	VK_CHECK(vk.bindBufferMemory(vkDevice, *vertexBuffer, (*pAlloc)->getMemory(), (*pAlloc)->getOffset()));
480
481	return vertexBuffer;
482}
483
484Move<VkImage> createImage2DAndBindMemory (Context&                          context,
485										  VkFormat                          format,
486										  deUint32                          width,
487										  deUint32                          height,
488										  VkImageUsageFlags                 usage,
489										  VkSampleCountFlagBits             sampleCount,
490										  de::details::MovePtr<Allocation>* pAlloc)
491{
492	const DeviceInterface&  vk               = context.getDeviceInterface();
493	const VkDevice          vkDevice         = context.getDevice();
494	const deUint32          queueFamilyIndex = context.getUniversalQueueFamilyIndex();
495	SimpleAllocator*        memAlloc         = new SimpleAllocator(vk, vkDevice, getPhysicalDeviceMemoryProperties(context.getInstanceInterface(), context.getPhysicalDevice()));
496
497	const VkImageCreateInfo colorImageParams =
498	{
499		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                                        // VkStructureType      sType;
500		DE_NULL,                                                                    // const void*          pNext;
501		0u,                                                                         // VkImageCreateFlags   flags;
502		VK_IMAGE_TYPE_2D,                                                           // VkImageType          imageType;
503		format,                                                                     // VkFormat             format;
504		{ width, height, 1u },                                                      // VkExtent3D           extent;
505		1u,                                                                         // deUint32             mipLevels;
506		1u,                                                                         // deUint32             arraySize;
507		sampleCount,                                                                // deUint32             samples;
508		VK_IMAGE_TILING_OPTIMAL,                                                    // VkImageTiling        tiling;
509		usage,                                                                      // VkImageUsageFlags    usage;
510		VK_SHARING_MODE_EXCLUSIVE,                                                  // VkSharingMode        sharingMode;
511		1u,                                                                         // deUint32             queueFamilyCount;
512		&queueFamilyIndex,                                                          // const deUint32*      pQueueFamilyIndices;
513		VK_IMAGE_LAYOUT_UNDEFINED,                                                  // VkImageLayout        initialLayout;
514	};
515
516	Move<VkImage> image = createImage(vk, vkDevice, &colorImageParams);
517
518	DE_ASSERT(pAlloc);
519	*pAlloc = memAlloc->allocate(getImageMemoryRequirements(vk, vkDevice, *image), MemoryRequirement::Any);
520	VK_CHECK(vk.bindImageMemory(vkDevice, *image, (*pAlloc)->getMemory(), (*pAlloc)->getOffset()));
521
522	return image;
523}
524
525// Test Classes
526class CacheTest : public vkt::TestCase
527{
528public:
529						  CacheTest(tcu::TestContext&           testContext,
530									const std::string&          name,
531									const std::string&          description,
532									const CacheTestParam*       param)
533							  : vkt::TestCase (testContext, name, description)
534							  , m_param (*param)
535							  { }
536	virtual               ~CacheTest (void) { }
537protected:
538	const CacheTestParam  m_param;
539};
540
541class CacheTestInstance : public vkt::TestInstance
542{
543public:
544	enum
545	{
546		PIPELINE_CACHE_NDX_NO_CACHE,
547		PIPELINE_CACHE_NDX_CACHED,
548		PIPELINE_CACHE_NDX_COUNT,
549	};
550							CacheTestInstance           (Context&                 context,
551														 const CacheTestParam*    param);
552	virtual                 ~CacheTestInstance          (void);
553	virtual tcu::TestStatus iterate                     (void);
554protected:
555	virtual tcu::TestStatus verifyTestResult            (void) = 0;
556	virtual void            prepareCommandBuffer        (void) = 0;
557protected:
558	const CacheTestParam*   m_param;
559
560	Move<VkCommandPool>     m_cmdPool;
561	Move<VkCommandBuffer>   m_cmdBuffer;
562	Move<VkFence>           m_fence;
563	Move<VkPipelineCache>   m_cache;
564};
565
566CacheTestInstance::CacheTestInstance (Context&                 context,
567									  const CacheTestParam*    param)
568	: TestInstance       (context)
569	, m_param            (param)
570{
571	const DeviceInterface&  vk               = m_context.getDeviceInterface();
572	const VkDevice          vkDevice         = m_context.getDevice();
573	const deUint32          queueFamilyIndex = context.getUniversalQueueFamilyIndex();
574
575	// Create command pool
576	{
577		const VkCommandPoolCreateInfo cmdPoolParams =
578		{
579			VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,   // VkStructureType      sType;
580			DE_NULL,                                      // const void*          pNext;
581			VK_COMMAND_POOL_CREATE_TRANSIENT_BIT,         // VkCmdPoolCreateFlags flags;
582			queueFamilyIndex,                             // deUint32             queueFamilyIndex;
583		};
584
585		m_cmdPool = createCommandPool(vk, vkDevice, &cmdPoolParams);
586	}
587
588	// Create command buffer
589	{
590		const VkCommandBufferAllocateInfo cmdAllocateParams =
591		{
592			VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType         sType;
593			DE_NULL,                                        // const void*             pNext;
594			*m_cmdPool,                                     // VkCommandPool           cmdPool;
595			VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel    level;
596			1u,                                             // deUint32                bufferCount;
597		};
598
599		m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, &cmdAllocateParams);
600	}
601
602	// Create fence
603	{
604		const VkFenceCreateInfo fenceParams =
605		{
606			VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,        // VkStructureType      sType;
607			DE_NULL,                                    // const void*          pNext;
608			0u,                                         // VkFenceCreateFlags   flags;
609		};
610
611		m_fence = createFence(vk, vkDevice, &fenceParams);
612	}
613
614	// Create the Pipeline Cache
615	{
616		const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
617		{
618			VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,           // VkStructureType             sType;
619			DE_NULL,                                                // const void*                 pNext;
620			0u,                                                     // VkPipelineCacheCreateFlags  flags;
621			0u,                                                     // deUintptr                   initialDataSize;
622			DE_NULL,                                                // const void*                 pInitialData;
623		};
624
625		m_cache = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
626	}
627}
628
629CacheTestInstance::~CacheTestInstance (void)
630{
631}
632
633tcu::TestStatus CacheTestInstance::iterate (void)
634{
635	const DeviceInterface&  vk       = m_context.getDeviceInterface();
636	const VkDevice          vkDevice = m_context.getDevice();
637	const VkQueue           queue    = m_context.getUniversalQueue();
638
639	prepareCommandBuffer();
640
641	VK_CHECK(vk.resetFences(vkDevice, 1u, &m_fence.get()));
642
643	const VkSubmitInfo          submitInfo =
644	{
645		VK_STRUCTURE_TYPE_SUBMIT_INFO,                      // VkStructureType             sType;
646		DE_NULL,                                            // const void*                 pNext;
647		0u,                                                 // deUint32                    waitSemaphoreCount;
648		DE_NULL,                                            // const VkSemaphore*          pWaitSemaphores;
649		(const VkPipelineStageFlags*)DE_NULL,               // const VkPipelineStageFlags* pWaitDstStageMask;
650		1u,                                                 // deUint32                    commandBufferCount;
651		&m_cmdBuffer.get(),                                 // const VkCommandBuffer*      pCommandBuffers;
652		0u,                                                 // deUint32                    signalSemaphoreCount;
653		DE_NULL,                                            // const VkSemaphore*          pSignalSemaphores;
654	};
655	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *m_fence));
656
657	VK_CHECK(vk.waitForFences(vkDevice, 1u, &m_fence.get(), true, ~(0ull) /* infinity*/));
658
659	return verifyTestResult();
660}
661
662class GraphicsCacheTest : public CacheTest
663{
664public:
665							GraphicsCacheTest   (tcu::TestContext&      testContext,
666												 const std::string&     name,
667												 const std::string&     description,
668												 const CacheTestParam*  param)
669								: CacheTest (testContext, name, description, param)
670								{ }
671	virtual                 ~GraphicsCacheTest  (void) { }
672	virtual void            initPrograms        (SourceCollections&      programCollection) const;
673	virtual TestInstance*   createInstance      (Context&                context) const;
674};
675
676class GraphicsCacheTestInstance : public CacheTestInstance
677{
678public:
679							GraphicsCacheTestInstance   (Context&              context,
680														 const CacheTestParam*  param);
681	virtual                 ~GraphicsCacheTestInstance  (void);
682protected:
683			void            prepareRenderPass           (VkFramebuffer framebuffer, VkPipeline pipeline);
684	virtual void            prepareCommandBuffer        (void);
685	virtual tcu::TestStatus verifyTestResult            (void);
686
687protected:
688	const tcu::UVec2                    m_renderSize;
689	const VkFormat                      m_colorFormat;
690	const VkFormat                      m_depthFormat;
691
692	Move<VkImage>                       m_depthImage;
693	de::MovePtr<Allocation>             m_depthImageAlloc;
694	de::MovePtr<Allocation>             m_colorImageAlloc[PIPELINE_CACHE_NDX_COUNT];
695	Move<VkImageView>                   m_depthAttachmentView;
696	VkImageMemoryBarrier				m_imageLayoutBarriers[3];
697
698	Move<VkBuffer>                      m_vertexBuffer;
699	de::MovePtr<Allocation>				m_vertexBufferMemory;
700	std::vector<Vertex4RGBA>            m_vertices;
701
702	SimpleGraphicsPipelineBuilder       m_pipelineBuilder;
703	Move<VkRenderPass>                  m_renderPass;
704
705	Move<VkImage>                       m_colorImage[PIPELINE_CACHE_NDX_COUNT];
706	Move<VkImageView>                   m_colorAttachmentView[PIPELINE_CACHE_NDX_COUNT];
707	Move<VkFramebuffer>                 m_framebuffer[PIPELINE_CACHE_NDX_COUNT];
708	Move<VkPipeline>                    m_pipeline[PIPELINE_CACHE_NDX_COUNT];
709};
710
711void GraphicsCacheTest::initPrograms (SourceCollections& programCollection) const
712{
713	for (deUint32 shaderNdx = 0; shaderNdx < m_param.getShaderCount(); shaderNdx++)
714	{
715		switch(m_param.getShaderFlag(shaderNdx))
716		{
717			case VK_SHADER_STAGE_VERTEX_BIT:
718				programCollection.glslSources.add("color_vert") << glu::VertexSource(
719					"#version 310 es\n"
720					"layout(location = 0) in vec4 position;\n"
721					"layout(location = 1) in vec4 color;\n"
722					"layout(location = 0) out highp vec4 vtxColor;\n"
723					"void main (void)\n"
724					"{\n"
725					"  gl_Position = position;\n"
726					"  vtxColor = color;\n"
727					"}\n");
728				break;
729
730			case VK_SHADER_STAGE_FRAGMENT_BIT:
731				programCollection.glslSources.add("color_frag") << glu::FragmentSource(
732					"#version 310 es\n"
733					"layout(location = 0) in highp vec4 vtxColor;\n"
734					"layout(location = 0) out highp vec4 fragColor;\n"
735					"void main (void)\n"
736					"{\n"
737					"  fragColor = vtxColor;\n"
738					"}\n");
739				break;
740
741			case VK_SHADER_STAGE_GEOMETRY_BIT:
742				programCollection.glslSources.add("dummy_geo") << glu::GeometrySource(
743					"#version 450 \n"
744					"layout(triangles) in;\n"
745					"layout(triangle_strip, max_vertices = 3) out;\n"
746					"layout(location = 0) in highp vec4 in_vtxColor[];\n"
747					"layout(location = 0) out highp vec4 vtxColor;\n"
748					"out gl_PerVertex { vec4 gl_Position; };\n"
749					"in gl_PerVertex { vec4 gl_Position; } gl_in[];\n"
750					"void main (void)\n"
751					"{\n"
752					"  for(int ndx=0; ndx<3; ndx++)\n"
753					"  {\n"
754					"    gl_Position = gl_in[ndx].gl_Position;\n"
755					"    vtxColor    = in_vtxColor[ndx];\n"
756					"    EmitVertex();\n"
757					"  }\n"
758					"  EndPrimitive();\n"
759					"}\n");
760				break;
761
762			case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
763				programCollection.glslSources.add("basic_tcs") << glu::TessellationControlSource(
764					"#version 450 \n"
765					"layout(vertices = 3) out;\n"
766					"layout(location = 0) in highp vec4 color[];\n"
767					"layout(location = 0) out highp vec4 vtxColor[];\n"
768					"out gl_PerVertex { vec4 gl_Position; } gl_out[3];\n"
769					"in gl_PerVertex { vec4 gl_Position; } gl_in[gl_MaxPatchVertices];\n"
770					"void main()\n"
771					"{\n"
772					"  gl_TessLevelOuter[0] = 4.0;\n"
773					"  gl_TessLevelOuter[1] = 4.0;\n"
774					"  gl_TessLevelOuter[2] = 4.0;\n"
775					"  gl_TessLevelInner[0] = 4.0;\n"
776					"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
777					"  vtxColor[gl_InvocationID] = color[gl_InvocationID];\n"
778					"}\n");
779				break;
780
781			case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
782				programCollection.glslSources.add("basic_tes") << glu::TessellationEvaluationSource(
783					"#version 450 \n"
784					"layout(triangles, fractional_even_spacing, ccw) in;\n"
785					"layout(location = 0) in highp vec4 colors[];\n"
786					"layout(location = 0) out highp vec4 vtxColor;\n"
787					"out gl_PerVertex { vec4 gl_Position; };\n"
788					"in gl_PerVertex { vec4 gl_Position; } gl_in[gl_MaxPatchVertices];\n"
789					"void main() \n"
790					"{\n"
791					"  float u = gl_TessCoord.x;\n"
792					"  float v = gl_TessCoord.y;\n"
793					"  float w = gl_TessCoord.z;\n"
794					"  vec4 pos = vec4(0);\n"
795					"  vec4 color = vec4(0);\n"
796					"  pos.xyz += u * gl_in[0].gl_Position.xyz;\n"
797					"  color.xyz += u * colors[0].xyz;\n"
798					"  pos.xyz += v * gl_in[1].gl_Position.xyz;\n"
799					"  color.xyz += v * colors[1].xyz;\n"
800					"  pos.xyz += w * gl_in[2].gl_Position.xyz;\n"
801					"  color.xyz += w * colors[2].xyz;\n"
802					"  pos.w = 1.0;\n"
803					"  color.w = 1.0;\n"
804					"  gl_Position = pos;\n"
805					"  vtxColor = color;\n"
806					"}\n");
807				break;
808
809			default:
810				DE_FATAL("Unknown Shader Stage!");
811				break;
812		};
813	}
814}
815
816TestInstance* GraphicsCacheTest::createInstance (Context& context) const
817{
818	return new GraphicsCacheTestInstance(context, &m_param);
819}
820
821GraphicsCacheTestInstance::GraphicsCacheTestInstance (Context&              context,
822													  const CacheTestParam* param)
823	: CacheTestInstance (context,param)
824	, m_renderSize      (32u, 32u)
825	, m_colorFormat     (VK_FORMAT_R8G8B8A8_UNORM)
826	, m_depthFormat     (VK_FORMAT_D16_UNORM)
827	, m_pipelineBuilder (context)
828{
829	const DeviceInterface&  vk               = m_context.getDeviceInterface();
830	const VkDevice          vkDevice         = m_context.getDevice();
831
832	// Create vertex buffer
833	{
834		m_vertexBuffer = createBufferAndBindMemory(m_context, 1024u, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &m_vertexBufferMemory);
835
836		m_vertices          = createOverlappingQuads();
837		// Load vertices into vertex buffer
838		deMemcpy(m_vertexBufferMemory->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
839		flushMappedMemoryRange(vk, vkDevice, m_vertexBufferMemory->getMemory(), m_vertexBufferMemory->getOffset(), 1024u);
840	}
841
842	// Create render pass
843	{
844		const VkAttachmentDescription colorAttachmentDescription =
845		{
846			0u,                                                 // VkAttachmentDescriptionFlags    flags;
847			m_colorFormat,                                      // VkFormat                        format;
848			VK_SAMPLE_COUNT_1_BIT,                              // VkSampleCountFlagBits           samples;
849			VK_ATTACHMENT_LOAD_OP_CLEAR,                        // VkAttachmentLoadOp              loadOp;
850			VK_ATTACHMENT_STORE_OP_STORE,                       // VkAttachmentStoreOp             storeOp;
851			VK_ATTACHMENT_LOAD_OP_DONT_CARE,                    // VkAttachmentLoadOp              stencilLoadOp;
852			VK_ATTACHMENT_STORE_OP_DONT_CARE,                   // VkAttachmentStoreOp             stencilStoreOp;
853			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,           // VkImageLayout                   initialLayout;
854			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,           // VkImageLayout                   finalLayout;
855		};
856
857		const VkAttachmentDescription depthAttachmentDescription =
858		{
859			0u,                                                 // VkAttachmentDescriptionFlags flags;
860			m_depthFormat,                                      // VkFormat                     format;
861			VK_SAMPLE_COUNT_1_BIT,                              // VkSampleCountFlagBits        samples;
862			VK_ATTACHMENT_LOAD_OP_CLEAR,                        // VkAttachmentLoadOp           loadOp;
863			VK_ATTACHMENT_STORE_OP_DONT_CARE,                   // VkAttachmentStoreOp          storeOp;
864			VK_ATTACHMENT_LOAD_OP_DONT_CARE,                    // VkAttachmentLoadOp           stencilLoadOp;
865			VK_ATTACHMENT_STORE_OP_DONT_CARE,                   // VkAttachmentStoreOp          stencilStoreOp;
866			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,   // VkImageLayout                initialLayout;
867			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,   // VkImageLayout                finalLayout;
868		};
869
870		const VkAttachmentDescription attachments[2] =
871		{
872			colorAttachmentDescription,
873			depthAttachmentDescription
874		};
875
876		const VkAttachmentReference colorAttachmentReference =
877		{
878			0u,                                                 // deUint32         attachment;
879			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL            // VkImageLayout    layout;
880		};
881
882		const VkAttachmentReference depthAttachmentReference =
883		{
884			1u,                                                 // deUint32         attachment;
885			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL    // VkImageLayout    layout;
886		};
887
888		const VkSubpassDescription subpassDescription =
889		{
890			0u,                                                 // VkSubpassDescriptionFlags        flags;
891			VK_PIPELINE_BIND_POINT_GRAPHICS,                    // VkPipelineBindPoint              pipelineBindPoint;
892			0u,                                                 // deUint32                         inputAttachmentCount;
893			DE_NULL,                                            // const VkAttachmentReference*     pInputAttachments;
894			1u,                                                 // deUint32                         colorAttachmentCount;
895			&colorAttachmentReference,                          // const VkAttachmentReference*     pColorAttachments;
896			DE_NULL,                                            // const VkAttachmentReference*     pResolveAttachments;
897			&depthAttachmentReference,                          // const VkAttachmentReference*     pDepthStencilAttachment;
898			0u,                                                 // deUint32                         preserveAttachmentCount;
899			DE_NULL                                             // const VkAttachmentReference*     pPreserveAttachments;
900		};
901
902		const VkRenderPassCreateInfo renderPassParams =
903		{
904			VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,          // VkStructureType                  sType;
905			DE_NULL,                                            // const void*                      pNext;
906			0u,                                                 // VkRenderPassCreateFlags          flags;
907			2u,                                                 // deUint32                         attachmentCount;
908			attachments,                                        // const VkAttachmentDescription*   pAttachments;
909			1u,                                                 // deUint32                         subpassCount;
910			&subpassDescription,                                // const VkSubpassDescription*      pSubpasses;
911			0u,                                                 // deUint32                         dependencyCount;
912			DE_NULL                                             // const VkSubpassDependency*       pDependencies;
913		};
914
915		m_renderPass = createRenderPass(vk, vkDevice, &renderPassParams);
916	}
917
918	const VkComponentMapping    ComponentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
919	// Create color image
920	{
921		m_colorImage[PIPELINE_CACHE_NDX_NO_CACHE] = createImage2DAndBindMemory(m_context,
922																			   m_colorFormat,
923																			   m_renderSize.x(),
924																			   m_renderSize.y(),
925																			   VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
926																			   VK_SAMPLE_COUNT_1_BIT,
927																			   &m_colorImageAlloc[PIPELINE_CACHE_NDX_NO_CACHE]);
928		m_colorImage[PIPELINE_CACHE_NDX_CACHED]   = createImage2DAndBindMemory(m_context,
929																			   m_colorFormat,
930																			   m_renderSize.x(),
931																			   m_renderSize.y(),
932																			   VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
933																			   VK_SAMPLE_COUNT_1_BIT,
934																			   &m_colorImageAlloc[PIPELINE_CACHE_NDX_CACHED]);
935	}
936
937	// Create depth image
938	{
939		m_depthImage = createImage2DAndBindMemory(m_context,
940												  m_depthFormat,
941												  m_renderSize.x(),
942												  m_renderSize.y(),
943												  VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
944												  VK_SAMPLE_COUNT_1_BIT,
945												  &m_depthImageAlloc);
946	}
947
948	// Set up image layout transition barriers
949	{
950		VkImageMemoryBarrier colorImageBarrier =
951		{
952			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
953			DE_NULL,											// const void*				pNext;
954			0u,													// VkAccessFlags			srcAccessMask;
955			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
956			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
957			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout			newLayout;
958			VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
959			VK_QUEUE_FAMILY_IGNORED,							// deUint32					dstQueueFamilyIndex;
960			*m_colorImage[PIPELINE_CACHE_NDX_NO_CACHE],			// VkImage					image;
961			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },		// VkImageSubresourceRange	subresourceRange;
962		};
963
964		m_imageLayoutBarriers[0] = colorImageBarrier;
965
966		colorImageBarrier.image = *m_colorImage[PIPELINE_CACHE_NDX_CACHED];
967		m_imageLayoutBarriers[1] = colorImageBarrier;
968
969		const VkImageMemoryBarrier depthImageBarrier =
970		{
971			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
972			DE_NULL,											// const void*				pNext;
973			0u,													// VkAccessFlags			srcAccessMask;
974			VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			dstAccessMask;
975			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
976			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout			newLayout;
977			VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
978			VK_QUEUE_FAMILY_IGNORED,							// deUint32					dstQueueFamilyIndex;
979			*m_depthImage,										// VkImage					image;
980			{ VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u },		// VkImageSubresourceRange	subresourceRange;
981		};
982
983		m_imageLayoutBarriers[2] = depthImageBarrier;
984	}
985	// Create color attachment view
986	{
987		VkImageViewCreateInfo colorAttachmentViewParams =
988		{
989			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType          sType;
990			DE_NULL,                                        // const void*              pNext;
991			0u,                                             // VkImageViewCreateFlags   flags;
992			*m_colorImage[PIPELINE_CACHE_NDX_NO_CACHE],     // VkImage                  image;
993			VK_IMAGE_VIEW_TYPE_2D,                          // VkImageViewType          viewType;
994			m_colorFormat,                                  // VkFormat                 format;
995			ComponentMappingRGBA,                           // VkComponentMapping       components;
996			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },  // VkImageSubresourceRange  subresourceRange;
997		};
998
999		m_colorAttachmentView[PIPELINE_CACHE_NDX_NO_CACHE] = createImageView(vk, vkDevice, &colorAttachmentViewParams);
1000
1001		colorAttachmentViewParams.image = *m_colorImage[PIPELINE_CACHE_NDX_CACHED];
1002		m_colorAttachmentView[PIPELINE_CACHE_NDX_CACHED] = createImageView(vk, vkDevice, &colorAttachmentViewParams);
1003	}
1004
1005	// Create depth attachment view
1006	{
1007		const VkImageViewCreateInfo depthAttachmentViewParams =
1008		{
1009			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,       // VkStructureType          sType;
1010			DE_NULL,                                        // const void*              pNext;
1011			0u,                                             // VkImageViewCreateFlags   flags;
1012			*m_depthImage,                                  // VkImage                  image;
1013			VK_IMAGE_VIEW_TYPE_2D,                          // VkImageViewType          viewType;
1014			m_depthFormat,                                  // VkFormat                 format;
1015			ComponentMappingRGBA,                           // VkComponentMapping       components;
1016			{ VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u },  // VkImageSubresourceRange  subresourceRange;
1017		};
1018
1019		m_depthAttachmentView = createImageView(vk, vkDevice, &depthAttachmentViewParams);
1020	}
1021
1022	// Create framebuffer
1023	{
1024		VkImageView attachmentBindInfos[2] =
1025		{
1026			*m_colorAttachmentView[PIPELINE_CACHE_NDX_NO_CACHE],
1027			*m_depthAttachmentView,
1028		};
1029
1030		const VkFramebufferCreateInfo framebufferParams =
1031		{
1032			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,          // VkStructureType              sType;
1033			DE_NULL,                                            // const void*                  pNext;
1034			0u,                                                 // VkFramebufferCreateFlags     flags;
1035			*m_renderPass,                                      // VkRenderPass                 renderPass;
1036			2u,                                                 // deUint32                     attachmentCount;
1037			attachmentBindInfos,                                // const VkImageView*           pAttachments;
1038			(deUint32)m_renderSize.x(),                         // deUint32                     width;
1039			(deUint32)m_renderSize.y(),                         // deUint32                     height;
1040			1u,                                                 // deUint32                     layers;
1041		};
1042
1043		m_framebuffer[PIPELINE_CACHE_NDX_NO_CACHE] = createFramebuffer(vk, vkDevice, &framebufferParams);
1044
1045		attachmentBindInfos[0] = *m_colorAttachmentView[PIPELINE_CACHE_NDX_CACHED];
1046		m_framebuffer[PIPELINE_CACHE_NDX_CACHED] = createFramebuffer(vk, vkDevice, &framebufferParams);
1047	}
1048
1049	// Bind shader stages
1050	VkPhysicalDeviceFeatures  features = m_context.getDeviceFeatures();
1051	for (deUint32 shaderNdx = 0; shaderNdx < m_param->getShaderCount(); shaderNdx++)
1052	{
1053		switch(m_param->getShaderFlag(shaderNdx))
1054		{
1055			case VK_SHADER_STAGE_VERTEX_BIT:
1056				m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_VERTEX_BIT, "color_vert", "main");
1057				break;
1058			case VK_SHADER_STAGE_FRAGMENT_BIT:
1059				m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_FRAGMENT_BIT, "color_frag", "main");
1060				break;
1061			case VK_SHADER_STAGE_GEOMETRY_BIT:
1062				if (features.geometryShader == VK_FALSE)
1063				{
1064					TCU_THROW(NotSupportedError, "Geometry Shader Not Supported");
1065				}
1066				else
1067				{
1068					m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_GEOMETRY_BIT, "dummy_geo", "main");
1069				}
1070				break;
1071			case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
1072				if (features.tessellationShader == VK_FALSE)
1073				{
1074					TCU_THROW(NotSupportedError, "Tessellation Not Supported");
1075				}
1076				else
1077				{
1078					m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "basic_tcs", "main");
1079					m_pipelineBuilder.enableTessellationStage(3);
1080				}
1081				break;
1082			case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
1083				if (features.tessellationShader == VK_FALSE)
1084				{
1085					TCU_THROW(NotSupportedError, "Tessellation Not Supported");
1086				}
1087				else
1088				{
1089					m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "basic_tes", "main");
1090					m_pipelineBuilder.enableTessellationStage(3);
1091				}
1092				break;
1093			default:
1094				DE_FATAL("Unknown Shader Stage!");
1095				break;
1096		};
1097	}
1098
1099	m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE] = m_pipelineBuilder.buildPipeline(m_renderSize, *m_renderPass, *m_cache);
1100	m_pipeline[PIPELINE_CACHE_NDX_CACHED]   = m_pipelineBuilder.buildPipeline(m_renderSize, *m_renderPass, *m_cache);
1101}
1102
1103GraphicsCacheTestInstance::~GraphicsCacheTestInstance (void)
1104{
1105}
1106
1107void GraphicsCacheTestInstance::prepareRenderPass (VkFramebuffer framebuffer, VkPipeline pipeline)
1108{
1109	const DeviceInterface&  vk               = m_context.getDeviceInterface();
1110
1111	const VkClearValue attachmentClearValues[2] =
1112	{
1113		defaultClearValue(m_colorFormat),
1114		defaultClearValue(m_depthFormat),
1115	};
1116
1117	const VkRenderPassBeginInfo renderPassBeginInfo =
1118	{
1119		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,               // VkStructureType      sType;
1120		DE_NULL,                                                // const void*          pNext;
1121		*m_renderPass,                                          // VkRenderPass         renderPass;
1122		framebuffer,                                            // VkFramebuffer        framebuffer;
1123		{ { 0, 0 }, { m_renderSize.x(), m_renderSize.y() } },   // VkRect2D             renderArea;
1124		2u,                                                     // deUint32             clearValueCount;
1125		attachmentClearValues                                   // const VkClearValue*  pClearValues;
1126	};
1127
1128	vk.cmdBeginRenderPass(*m_cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1129
1130	vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
1131	VkDeviceSize offsets = 0u;
1132	vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &offsets);
1133	vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1u, 0u, 0u);
1134
1135	vk.cmdEndRenderPass(*m_cmdBuffer);
1136}
1137
1138void GraphicsCacheTestInstance::prepareCommandBuffer (void)
1139{
1140	const DeviceInterface&  vk               = m_context.getDeviceInterface();
1141
1142	const VkCommandBufferBeginInfo cmdBufferBeginInfo =
1143	{
1144		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                  sType;
1145		DE_NULL,                                        // const void*                      pNext;
1146		0u,                                             // VkCommandBufferUsageFlags        flags;
1147		(const VkCommandBufferInheritanceInfo*)DE_NULL,
1148	};
1149
1150	VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1151
1152	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0,
1153		0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(m_imageLayoutBarriers), m_imageLayoutBarriers);
1154
1155	prepareRenderPass(*m_framebuffer[PIPELINE_CACHE_NDX_NO_CACHE], *m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE]);
1156
1157	// After the first render pass, the images are in correct layouts
1158
1159	prepareRenderPass(*m_framebuffer[PIPELINE_CACHE_NDX_CACHED], *m_pipeline[PIPELINE_CACHE_NDX_CACHED]);
1160
1161	VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1162}
1163
1164tcu::TestStatus GraphicsCacheTestInstance::verifyTestResult (void)
1165{
1166	const DeviceInterface&  vk               = m_context.getDeviceInterface();
1167	const VkDevice          vkDevice         = m_context.getDevice();
1168	const deUint32          queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1169	SimpleAllocator*        memAlloc         = new SimpleAllocator(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
1170
1171	const VkQueue                   queue               = m_context.getUniversalQueue();
1172	de::MovePtr<tcu::TextureLevel>  resultNoCache       = readColorAttachment(vk,
1173																			  vkDevice,
1174																			  queue,
1175																			  queueFamilyIndex,
1176																			  *memAlloc,
1177																			  *m_colorImage[PIPELINE_CACHE_NDX_NO_CACHE],
1178																			  m_colorFormat,
1179																			  m_renderSize);
1180	de::MovePtr<tcu::TextureLevel>  resultCache         = readColorAttachment(vk,
1181																			  vkDevice,
1182																			  queue,
1183																			  queueFamilyIndex,
1184																			  *memAlloc,
1185																			  *m_colorImage[PIPELINE_CACHE_NDX_CACHED],
1186																			  m_colorFormat,
1187																			  m_renderSize);
1188
1189	bool compareOk = tcu::intThresholdCompare(m_context.getTestContext().getLog(),
1190											  "IntImageCompare",
1191											  "Image comparison",
1192											  resultNoCache->getAccess(),
1193											  resultCache->getAccess(),
1194											  tcu::UVec4(1, 1, 1, 1),
1195											  tcu::COMPARE_LOG_RESULT);
1196
1197	if (compareOk)
1198		return tcu::TestStatus::pass("Render images w/o cached pipeline match.");
1199	else
1200		return tcu::TestStatus::fail("Render Images mismatch.");
1201}
1202
1203class ComputeCacheTest : public CacheTest
1204{
1205public:
1206							ComputeCacheTest    (tcu::TestContext&      testContext,
1207												 const std::string&     name,
1208												 const std::string&     description,
1209												 const CacheTestParam*  param)
1210								: CacheTest (testContext, name, description, param)
1211								{ }
1212	virtual                 ~ComputeCacheTest   (void) { }
1213	virtual void            initPrograms        (SourceCollections&      programCollection) const;
1214	virtual TestInstance*   createInstance      (Context&                context) const;
1215};
1216
1217class ComputeCacheTestInstance : public CacheTestInstance
1218{
1219public:
1220							ComputeCacheTestInstance    (Context&               context,
1221														 const CacheTestParam*  param);
1222	virtual                 ~ComputeCacheTestInstance   (void);
1223	virtual void            prepareCommandBuffer        (void);
1224protected:
1225	virtual tcu::TestStatus verifyTestResult            (void);
1226			void            buildBuffers                (void);
1227			void            buildDescriptorSets         (deUint32 ndx);
1228			void            buildShader                 (void);
1229			void            buildPipeline               (deUint32 ndx);
1230protected:
1231	Move<VkBuffer>              m_inputBuf;
1232	de::MovePtr<Allocation>     m_inputBufferAlloc;
1233	Move<VkShaderModule>        m_computeShaderModule;
1234
1235	Move<VkBuffer>              m_outputBuf[PIPELINE_CACHE_NDX_COUNT];
1236	de::MovePtr<Allocation>     m_outputBufferAlloc[PIPELINE_CACHE_NDX_COUNT];
1237
1238	Move<VkDescriptorPool>      m_descriptorPool[PIPELINE_CACHE_NDX_COUNT];
1239	Move<VkDescriptorSetLayout> m_descriptorSetLayout[PIPELINE_CACHE_NDX_COUNT];
1240	Move<VkDescriptorSet>       m_descriptorSet[PIPELINE_CACHE_NDX_COUNT];
1241
1242	Move<VkPipelineLayout>      m_pipelineLayout[PIPELINE_CACHE_NDX_COUNT];
1243	Move<VkPipeline>            m_pipeline[PIPELINE_CACHE_NDX_COUNT];
1244};
1245
1246void ComputeCacheTest::initPrograms (SourceCollections& programCollection) const
1247{
1248	programCollection.glslSources.add("basic_compute") << glu::ComputeSource(
1249		"#version 310 es\n"
1250		"layout(local_size_x = 1) in;\n"
1251		"layout(std430) buffer;\n"
1252		"layout(binding = 0) readonly buffer Input0\n"
1253		"{\n"
1254		"  vec4 elements[];\n"
1255		"} input_data0;\n"
1256		"layout(binding = 1) writeonly buffer Output\n"
1257		"{\n"
1258		"  vec4 elements[];\n"
1259		"} output_data;\n"
1260		"void main()\n"
1261		"{\n"
1262		"  uint ident = gl_GlobalInvocationID.x;\n"
1263		"  output_data.elements[ident] = input_data0.elements[ident] * input_data0.elements[ident];\n"
1264		"}");
1265}
1266
1267TestInstance* ComputeCacheTest::createInstance (Context& context) const
1268{
1269	return new ComputeCacheTestInstance(context, &m_param);
1270}
1271
1272void ComputeCacheTestInstance::buildBuffers (void)
1273{
1274	const DeviceInterface&  vk               = m_context.getDeviceInterface();
1275	const VkDevice          vkDevice         = m_context.getDevice();
1276
1277	// Create buffer object, allocate storage, and generate input data
1278	const VkDeviceSize          size                = sizeof(tcu::Vec4) * 128u;
1279	m_inputBuf = createBufferAndBindMemory(m_context, size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, &m_inputBufferAlloc);
1280
1281	// Initialize input buffer
1282	tcu::Vec4* pVec = reinterpret_cast<tcu::Vec4*>(m_inputBufferAlloc->getHostPtr());
1283	for (deUint32 ndx = 0u; ndx < 128u; ndx++)
1284	{
1285		for (deUint32 component = 0u; component < 4u; component++)
1286			pVec[ndx][component]= (float)(ndx * (component + 1u));
1287	}
1288	flushMappedMemoryRange(vk, vkDevice, m_inputBufferAlloc->getMemory(), m_inputBufferAlloc->getOffset(), size);
1289
1290	// Clear the output buffer
1291	for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
1292	{
1293		m_outputBuf[ndx] = createBufferAndBindMemory(m_context, size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, &m_outputBufferAlloc[ndx]);
1294
1295		pVec = reinterpret_cast<tcu::Vec4*>(m_outputBufferAlloc[ndx]->getHostPtr());
1296		memset(pVec, 0u, size);
1297		flushMappedMemoryRange(vk, vkDevice, m_outputBufferAlloc[ndx]->getMemory(), m_outputBufferAlloc[ndx]->getOffset(), size);
1298	}
1299}
1300
1301void ComputeCacheTestInstance::buildDescriptorSets (deUint32 ndx)
1302{
1303	const DeviceInterface&  vk               = m_context.getDeviceInterface();
1304	const VkDevice          vkDevice         = m_context.getDevice();
1305
1306	// Create descriptor set layout
1307	DescriptorSetLayoutBuilder descLayoutBuilder;
1308
1309	for (deUint32 bindingNdx = 0u; bindingNdx < 2u; bindingNdx++)
1310		descLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
1311
1312	m_descriptorSetLayout[ndx] = descLayoutBuilder.build(vk, vkDevice);
1313
1314	std::vector<VkDescriptorBufferInfo>        descriptorInfos;
1315	descriptorInfos.push_back(makeDescriptorBufferInfo(*m_inputBuf, 0u, sizeof(tcu::Vec4) * 128u));
1316	descriptorInfos.push_back(makeDescriptorBufferInfo(*m_outputBuf[ndx], 0u, sizeof(tcu::Vec4) * 128u));
1317
1318	// Create descriptor pool
1319	m_descriptorPool[ndx] = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2u).build(vk,
1320																										 vkDevice,
1321																										 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
1322																										 1u);
1323
1324	// Create descriptor set
1325	const VkDescriptorSetAllocateInfo descriptorSetAllocInfo =
1326	{
1327		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,     // VkStructureType                 sType;
1328		DE_NULL,                                            // const void*                     pNext;
1329		*m_descriptorPool[ndx],                             // VkDescriptorPool                descriptorPool;
1330		1u,                                                 // deUint32                        setLayoutCount;
1331		&m_descriptorSetLayout[ndx].get(),                  // const VkDescriptorSetLayout*    pSetLayouts;
1332	};
1333	m_descriptorSet[ndx] = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocInfo);
1334
1335	DescriptorSetUpdateBuilder  builder;
1336	for (deUint32 descriptorNdx = 0u; descriptorNdx < 2u; descriptorNdx++)
1337	{
1338		builder.writeSingle(*m_descriptorSet[ndx],
1339							DescriptorSetUpdateBuilder::Location::binding(descriptorNdx),
1340							VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
1341							&descriptorInfos[descriptorNdx]);
1342	}
1343	builder.update(vk, vkDevice);
1344}
1345
1346void ComputeCacheTestInstance::buildShader (void)
1347{
1348	const DeviceInterface&  vk               = m_context.getDeviceInterface();
1349	const VkDevice          vkDevice         = m_context.getDevice();
1350
1351	// Create compute shader
1352	VkShaderModuleCreateInfo shaderModuleCreateInfo =
1353	{
1354		VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,                                    // VkStructureType             sType;
1355		DE_NULL,                                                                        // const void*                 pNext;
1356		0u,                                                                             // VkShaderModuleCreateFlags   flags;
1357		m_context.getBinaryCollection().get("basic_compute").getSize(),                 // deUintptr                   codeSize;
1358		(deUint32*)m_context.getBinaryCollection().get("basic_compute").getBinary(),    // const deUint32*             pCode;
1359	};
1360	m_computeShaderModule = createShaderModule(vk, vkDevice, &shaderModuleCreateInfo);
1361}
1362
1363void ComputeCacheTestInstance::buildPipeline (deUint32 ndx)
1364{
1365	const DeviceInterface&  vk               = m_context.getDeviceInterface();
1366	const VkDevice          vkDevice         = m_context.getDevice();
1367
1368	// Create compute pipeline layout
1369	const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1370	{
1371		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,  // VkStructureType                 sType;
1372		DE_NULL,                                        // const void*                     pNext;
1373		0u,                                             // VkPipelineLayoutCreateFlags     flags;
1374		1u,                                             // deUint32                        setLayoutCount;
1375		&m_descriptorSetLayout[ndx].get(),              // const VkDescriptorSetLayout*    pSetLayouts;
1376		0u,                                             // deUint32                        pushConstantRangeCount;
1377		DE_NULL,                                        // const VkPushConstantRange*      pPushConstantRanges;
1378	};
1379
1380	m_pipelineLayout[ndx] = createPipelineLayout(vk, vkDevice, &pipelineLayoutCreateInfo);
1381
1382	const VkPipelineShaderStageCreateInfo stageCreateInfo =
1383	{
1384		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType                     sType;
1385		DE_NULL,                                             // const void*                         pNext;
1386		0u,                                                  // VkPipelineShaderStageCreateFlags    flags;
1387		VK_SHADER_STAGE_COMPUTE_BIT,                         // VkShaderStageFlagBits               stage;
1388		*m_computeShaderModule,                              // VkShaderModule                      module;
1389		"main",                                              // const char*                         pName;
1390		DE_NULL,                                             // const VkSpecializationInfo*         pSpecializationInfo;
1391	};
1392
1393	const VkComputePipelineCreateInfo pipelineCreateInfo =
1394	{
1395		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,      // VkStructureType                 sType;
1396		DE_NULL,                                             // const void*                     pNext;
1397		0u,                                                  // VkPipelineCreateFlags           flags;
1398		stageCreateInfo,                                     // VkPipelineShaderStageCreateInfo stage;
1399		*m_pipelineLayout[ndx],                              // VkPipelineLayout                layout;
1400		(VkPipeline)0,                                       // VkPipeline                      basePipelineHandle;
1401		0u,                                                  // deInt32                         basePipelineIndex;
1402	};
1403
1404	m_pipeline[ndx] = createComputePipeline(vk, vkDevice, *m_cache, &pipelineCreateInfo);
1405}
1406
1407ComputeCacheTestInstance::ComputeCacheTestInstance (Context&              context,
1408												    const CacheTestParam*  param)
1409	: CacheTestInstance (context, param)
1410{
1411	buildBuffers();
1412
1413	buildDescriptorSets(PIPELINE_CACHE_NDX_NO_CACHE);
1414
1415	buildDescriptorSets(PIPELINE_CACHE_NDX_CACHED);
1416
1417	buildShader();
1418
1419	buildPipeline(PIPELINE_CACHE_NDX_NO_CACHE);
1420
1421	buildPipeline(PIPELINE_CACHE_NDX_CACHED);
1422}
1423
1424ComputeCacheTestInstance::~ComputeCacheTestInstance (void)
1425{
1426}
1427
1428void ComputeCacheTestInstance::prepareCommandBuffer (void)
1429{
1430	const DeviceInterface&  vk               = m_context.getDeviceInterface();
1431
1432	const VkCommandBufferBeginInfo cmdBufferBeginInfo =
1433	{
1434		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,    // VkStructureType                  sType;
1435		DE_NULL,                                        // const void*                      pNext;
1436		0u,                                             // VkCommandBufferUsageFlags        flags;
1437		(const VkCommandBufferInheritanceInfo*)DE_NULL,
1438	};
1439
1440	VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
1441
1442	for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
1443	{
1444		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipeline[ndx]);
1445		vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout[ndx], 0u, 1u, &m_descriptorSet[ndx].get(), 0u, DE_NULL);
1446		vk.cmdDispatch(*m_cmdBuffer, 128u, 1u, 1u);
1447	}
1448
1449	VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
1450}
1451
1452tcu::TestStatus ComputeCacheTestInstance::verifyTestResult (void)
1453{
1454	const DeviceInterface&  vk               = m_context.getDeviceInterface();
1455	const VkDevice          vkDevice         = m_context.getDevice();
1456
1457	// Read the content of output buffers
1458	invalidateMappedMemoryRange(vk,
1459								vkDevice,
1460								m_outputBufferAlloc[PIPELINE_CACHE_NDX_NO_CACHE]->getMemory(),
1461								m_outputBufferAlloc[PIPELINE_CACHE_NDX_NO_CACHE]->getOffset(),
1462								sizeof(tcu::Vec4) * 128u);
1463
1464	invalidateMappedMemoryRange(vk,
1465								vkDevice,
1466								m_outputBufferAlloc[PIPELINE_CACHE_NDX_CACHED]->getMemory(),
1467								m_outputBufferAlloc[PIPELINE_CACHE_NDX_CACHED]->getOffset(),
1468								sizeof(tcu::Vec4) * 128u);
1469	// Compare the content
1470	deUint8* bufNoCache = reinterpret_cast<deUint8*>(m_outputBufferAlloc[PIPELINE_CACHE_NDX_NO_CACHE]->getHostPtr());
1471	deUint8* bufCached  = reinterpret_cast<deUint8*>(m_outputBufferAlloc[PIPELINE_CACHE_NDX_CACHED]->getHostPtr());
1472	for (deUint32 ndx = 0u; ndx < sizeof(tcu::Vec4) * 128u; ndx++)
1473	{
1474		if (bufNoCache[ndx] != bufCached[ndx])
1475		{
1476			return tcu::TestStatus::fail("Output buffers w/o cached pipeline mismatch.");
1477		}
1478	}
1479
1480	return tcu::TestStatus::pass("Output buffers w/o cached pipeline match.");
1481}
1482
1483class MergeCacheTest : public GraphicsCacheTest
1484{
1485public:
1486							MergeCacheTest      (tcu::TestContext&      testContext,
1487												 const std::string&     name,
1488												 const std::string&     description,
1489												 const CacheTestParam*  param)
1490								: GraphicsCacheTest (testContext, name, description, param)
1491								{ }
1492	virtual                 ~MergeCacheTest     (void) { }
1493	virtual TestInstance*   createInstance      (Context&               context) const;
1494};
1495
1496class MergeCacheTestInstance : public GraphicsCacheTestInstance
1497{
1498public:
1499							MergeCacheTestInstance  (Context&              context,
1500													 const CacheTestParam*  param);
1501	virtual                 ~MergeCacheTestInstance (void);
1502protected:
1503protected:
1504	Move<VkPipelineCache>   m_cacheGetData;
1505	Move<VkPipelineCache>   m_cacheEmpty;
1506	Move<VkPipelineCache>   m_cacheMerged;
1507	deUint8*                m_data;
1508};
1509
1510TestInstance* MergeCacheTest::createInstance (Context& context) const
1511{
1512	return new MergeCacheTestInstance(context, &m_param);
1513}
1514
1515MergeCacheTestInstance::MergeCacheTestInstance (Context& context, const CacheTestParam* param)
1516	: GraphicsCacheTestInstance (context, param)
1517	, m_data                    (DE_NULL)
1518{
1519	const DeviceInterface&  vk               = m_context.getDeviceInterface();
1520	const VkDevice          vkDevice         = m_context.getDevice();
1521
1522	// Create more pipeline caches
1523	{
1524		// Create a empty cache as one of source cache
1525		VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
1526		{
1527			VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,           // VkStructureType             sType;
1528			DE_NULL,                                                // const void*                 pNext;
1529			0u,                                                     // VkPipelineCacheCreateFlags  flags;
1530			0u,                                                     // deUintptr                   initialDataSize;
1531			DE_NULL,                                                // const void*                 pInitialData;
1532		};
1533		m_cacheEmpty = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
1534
1535		// Create a empty cache for merge destination cache
1536		m_cacheMerged = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
1537
1538		// Create a cache with init data from m_cache
1539		size_t  dataSize = 0u;
1540		VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, DE_NULL));
1541
1542		m_data = new deUint8[dataSize];
1543		DE_ASSERT(m_data);
1544		VK_CHECK(vk.getPipelineCacheData(vkDevice, *m_cache, (deUintptr*)&dataSize, (void*)m_data));
1545
1546		pipelineCacheCreateInfo.initialDataSize = dataSize;
1547		pipelineCacheCreateInfo.pInitialData = m_data;
1548		m_cacheGetData = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
1549	}
1550
1551	// Merge the caches
1552	const VkPipelineCache sourceCaches[] =
1553	{
1554		*m_cacheEmpty,
1555		*m_cacheGetData,
1556	};
1557	VK_CHECK(vk.mergePipelineCaches(vkDevice, *m_cacheMerged, 2u, sourceCaches));
1558
1559	// Create pipeline from merged cache
1560	m_pipeline[PIPELINE_CACHE_NDX_CACHED] = m_pipelineBuilder.buildPipeline(m_renderSize, *m_renderPass, *m_cacheMerged);
1561}
1562
1563MergeCacheTestInstance::~MergeCacheTestInstance (void)
1564{
1565	delete[] m_data;
1566}
1567
1568} // anonymous
1569
1570tcu::TestCaseGroup* createCacheTests (tcu::TestContext& testCtx)
1571{
1572
1573	de::MovePtr<tcu::TestCaseGroup> cacheTests (new tcu::TestCaseGroup(testCtx, "cache", "pipeline cache tests"));
1574
1575	// Graphics Pipeline Tests
1576	{
1577		de::MovePtr<tcu::TestCaseGroup> graphicsTests (new tcu::TestCaseGroup(testCtx, "graphics_tests", "Test pipeline cache with graphics pipeline."));
1578
1579		const VkShaderStageFlagBits testParamShaders0[] =
1580		{
1581			VK_SHADER_STAGE_VERTEX_BIT,
1582			VK_SHADER_STAGE_FRAGMENT_BIT,
1583		};
1584		const VkShaderStageFlagBits testParamShaders1[] =
1585		{
1586			VK_SHADER_STAGE_VERTEX_BIT,
1587			VK_SHADER_STAGE_GEOMETRY_BIT,
1588			VK_SHADER_STAGE_FRAGMENT_BIT,
1589		};
1590		const VkShaderStageFlagBits testParamShaders2[] =
1591		{
1592			VK_SHADER_STAGE_VERTEX_BIT,
1593			VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
1594			VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1595			VK_SHADER_STAGE_FRAGMENT_BIT,
1596		};
1597		const CacheTestParam* testParams[] =
1598		{
1599			new CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0)),
1600			new CacheTestParam(testParamShaders1, DE_LENGTH_OF_ARRAY(testParamShaders1)),
1601			new CacheTestParam(testParamShaders2, DE_LENGTH_OF_ARRAY(testParamShaders2)),
1602		};
1603
1604		for(deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1605		{
1606			graphicsTests->addChild(newTestCase<GraphicsCacheTest>(testCtx,testParams[i]));
1607			delete testParams[i];
1608		}
1609		cacheTests->addChild(graphicsTests.release());
1610	}
1611
1612	// Graphics Pipeline Tests
1613	{
1614		de::MovePtr<tcu::TestCaseGroup> computeTests (new tcu::TestCaseGroup(testCtx, "compute_tests", "Test pipeline cache with compute pipeline."));
1615
1616		const VkShaderStageFlagBits testParamShaders0[] =
1617		{
1618			VK_SHADER_STAGE_COMPUTE_BIT,
1619		};
1620
1621		const CacheTestParam* testParams[] =
1622		{
1623			new CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0)),
1624		};
1625		for(deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1626		{
1627			computeTests->addChild(newTestCase<ComputeCacheTest>(testCtx,testParams[i]));
1628			delete testParams[i];
1629		}
1630		cacheTests->addChild(computeTests.release());
1631	}
1632
1633	// Misc Tests
1634	{
1635		de::MovePtr<tcu::TestCaseGroup> miscTests (new tcu::TestCaseGroup(testCtx, "misc_tests", "Misc tests that can not be categorized to other group."));
1636
1637		const VkShaderStageFlagBits testParamShaders[] =
1638		{
1639			VK_SHADER_STAGE_VERTEX_BIT,
1640			VK_SHADER_STAGE_FRAGMENT_BIT,
1641		};
1642
1643		CacheTestParam* testParam = new CacheTestParam(testParamShaders, DE_LENGTH_OF_ARRAY(testParamShaders));
1644		miscTests->addChild(new MergeCacheTest(testCtx,
1645											   "merge_cache_test",
1646											   "Merge the caches test.",
1647											   testParam));
1648		delete testParam;
1649
1650		cacheTests->addChild(miscTests.release());
1651	}
1652
1653	return cacheTests.release();
1654}
1655
1656} // pipeline
1657
1658} // vkt
1659