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