• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 The Khronos Group Inc.
6  * Copyright (c) 2019 Valve Corporation.
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 "vktPipelineCreationFeedbackTests.hpp"
26 #include "vktPipelineVertexUtil.hpp"
27 #include "vktTestCase.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vkMemUtil.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkRefUtil.hpp"
32 #include "vkTypeUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "tcuTestLog.hpp"
35 
36 #include <sstream>
37 #include <vector>
38 
39 namespace vkt
40 {
41 namespace pipeline
42 {
43 
44 using namespace vk;
45 
46 namespace
47 {
48 enum
49 {
50 	VK_MAX_SHADER_STAGES = 6,
51 };
52 
53 enum
54 {
55 	PIPELINE_CACHE_NDX_NO_CACHE = 0,
56 	PIPELINE_CACHE_NDX_DERIVATIVE = 1,
57 	PIPELINE_CACHE_NDX_CACHED = 2,
58 	PIPELINE_CACHE_NDX_COUNT,
59 };
60 
61 // helper functions
62 
getShaderFlagStr(const VkShaderStageFlagBits shader,bool isDescription)63 std::string getShaderFlagStr (const VkShaderStageFlagBits	shader,
64 							  bool							isDescription)
65 {
66 	std::ostringstream desc;
67 	switch(shader)
68 	{
69 		case VK_SHADER_STAGE_VERTEX_BIT:
70 		{
71 			desc << ((isDescription) ? "vertex stage" : "vertex_stage");
72 			break;
73 		}
74 		case VK_SHADER_STAGE_FRAGMENT_BIT:
75 		{
76 			desc << ((isDescription) ? "fragment stage" : "fragment_stage");
77 			break;
78 		}
79 		case VK_SHADER_STAGE_GEOMETRY_BIT:
80 		{
81 			desc << ((isDescription) ? "geometry stage" : "geometry_stage");
82 			break;
83 		}
84 		case VK_SHADER_STAGE_COMPUTE_BIT:
85 		{
86 			desc << ((isDescription) ? "compute stage" : "compute_stage");
87 			break;
88 		}
89 		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
90 		{
91 			desc << ((isDescription) ? "tessellation control stage" : "tessellation_control_stage");
92 			break;
93 		}
94 		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
95 		{
96 			desc << ((isDescription) ? "tessellation evaluation stage" : "tessellation_evaluation_stage");
97 			break;
98 		}
99 	  default:
100 		desc << "unknown shader stage!";
101 		DE_FATAL("Unknown shader Stage!");
102 		break;
103 	}
104 
105 	return desc.str();
106 }
107 
getCaseStr(const deUint32 ndx)108 std::string getCaseStr (const deUint32 ndx)
109 {
110 	std::ostringstream desc;
111 	switch(ndx)
112 	{
113 		case PIPELINE_CACHE_NDX_NO_CACHE:
114 		{
115 			desc << "No cached pipeline";
116 			break;
117 		}
118 		case PIPELINE_CACHE_NDX_CACHED:
119 		{
120 			desc << "Cached pipeline";
121 			break;
122 		}
123 		case PIPELINE_CACHE_NDX_DERIVATIVE:
124 		{
125 			desc << "Pipeline derivative";
126 			break;
127 		}
128 	  default:
129 		desc << "Unknown case";
130 		DE_FATAL("Unknown case!");
131 		break;
132 	}
133 
134 	return desc.str();
135 }
136 
137 // helper classes
138 class CacheTestParam
139 {
140 public:
141 								CacheTestParam				(const VkShaderStageFlagBits*	shaders,
142 															 deUint32						count,
143 															 deBool							noCache,
144 															 deBool							delayedDestroy);
145 	virtual					~CacheTestParam					(void);
146 	virtual const std::string	generateTestName			(void)			const;
147 	virtual const std::string	generateTestDescription		(void)			const;
getShaderFlag(deUint32 ndx) const148 	VkShaderStageFlagBits		getShaderFlag				(deUint32 ndx)	const	{ return m_shaders[ndx]; }
getShaderCount(void) const149 	deUint32					getShaderCount				(void)			const	{ return (deUint32)m_shaderCount; }
isCacheDisabled(void) const150 	deBool						isCacheDisabled				(void)			const	{ return m_noCache; }
isDelayedDestroy(void) const151 	deBool						isDelayedDestroy			(void)			const	{ return m_delayedDestroy; }
152 
153 protected:
154 	VkShaderStageFlagBits		m_shaders[VK_MAX_SHADER_STAGES];
155 	size_t						m_shaderCount;
156 	bool						m_noCache;
157 	bool						m_delayedDestroy;
158 };
159 
CacheTestParam(const VkShaderStageFlagBits * shaders,deUint32 count,deBool noCache,deBool delayedDestroy)160 CacheTestParam::CacheTestParam (const VkShaderStageFlagBits* shaders, deUint32 count, deBool noCache, deBool delayedDestroy)
161 {
162 	DE_ASSERT(count <= VK_MAX_SHADER_STAGES);
163 	for (deUint32 ndx = 0; ndx < count; ndx++)
164 		m_shaders[ndx] = shaders[ndx];
165 	m_shaderCount		= count;
166 	m_noCache			= noCache;
167 	m_delayedDestroy	= delayedDestroy;
168 }
169 
~CacheTestParam(void)170 CacheTestParam::~CacheTestParam (void)
171 {
172 }
173 
generateTestName(void) const174 const std::string CacheTestParam::generateTestName (void) const
175 {
176 	std::string result(getShaderFlagStr(m_shaders[0], false));
177 	std::string cacheString [] = { "", "_no_cache" };
178 	std::string delayedDestroyString [] = { "", "_delayed_destroy" };
179 
180 	for(deUint32 ndx = 1; ndx < m_shaderCount; ndx++)
181 		result += '_' + getShaderFlagStr(m_shaders[ndx], false) + cacheString[m_noCache ? 1 : 0] + delayedDestroyString[m_delayedDestroy ? 1 : 0];
182 
183 	if (m_shaderCount == 1)
184 		result += cacheString[m_noCache ? 1 : 0] + delayedDestroyString[m_delayedDestroy ? 1 : 0];
185 
186 	return result;
187 }
188 
generateTestDescription(void) const189 const std::string CacheTestParam::generateTestDescription (void) const
190 {
191 	std::string result("Get pipeline creation feedback with " + getShaderFlagStr(m_shaders[0], true));
192 	if (m_noCache)
193 		result += " with no cache";
194 	if (m_delayedDestroy)
195 		result += " with delayed destroy";
196 
197 	for(deUint32 ndx = 1; ndx < m_shaderCount; ndx++)
198 		result += ' ' + getShaderFlagStr(m_shaders[ndx], true);
199 
200 	return result;
201 }
202 
203 class SimpleGraphicsPipelineBuilder
204 {
205 public:
206 							SimpleGraphicsPipelineBuilder	(Context&						context);
~SimpleGraphicsPipelineBuilder(void)207 							~SimpleGraphicsPipelineBuilder	(void) { }
208 	void					bindShaderStage					(VkShaderStageFlagBits			stage,
209 															 const char*					sourceName,
210 															 const char*					entryName);
211 	void					enableTessellationStage			(deUint32						patchControlPoints);
212 	VkPipeline				buildPipeline					(tcu::UVec2						renderSize,
213 															 VkRenderPass					renderPass,
214 															 VkPipelineCache				cache,
215 															 VkPipelineLayout				pipelineLayout,
216 															 VkPipelineCreationFeedbackEXT	*pipelineCreationFeedback,
217 															 VkPipelineCreationFeedbackEXT	*pipelineStageCreationFeedbacks,
218 															 VkPipeline						basePipelineHandle);
219 	void					resetBuilder					(void);
220 
221 protected:
222 	Context&							m_context;
223 
224 	Move<VkShaderModule>				m_shaderModules[VK_MAX_SHADER_STAGES];
225 	deUint32							m_shaderStageCount;
226 	VkPipelineShaderStageCreateInfo	m_shaderStageInfo[VK_MAX_SHADER_STAGES];
227 
228 	deUint32							m_patchControlPoints;
229 };
230 
SimpleGraphicsPipelineBuilder(Context & context)231 SimpleGraphicsPipelineBuilder::SimpleGraphicsPipelineBuilder (Context& context)
232 	: m_context(context)
233 {
234 	m_patchControlPoints = 0;
235 	m_shaderStageCount   = 0;
236 }
237 
resetBuilder(void)238 void SimpleGraphicsPipelineBuilder::resetBuilder (void)
239 {
240 	m_shaderStageCount = 0;
241 }
242 
bindShaderStage(VkShaderStageFlagBits stage,const char * sourceName,const char * entryName)243 void SimpleGraphicsPipelineBuilder::bindShaderStage (VkShaderStageFlagBits	stage,
244 													 const char*			sourceName,
245 													 const char*			entryName)
246 {
247 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
248 	const VkDevice			vkDevice	= m_context.getDevice();
249 
250 	// Create shader module
251 	deUint32*				code		= (deUint32*)m_context.getBinaryCollection().get(sourceName).getBinary();
252 	deUint32				codeSize	= (deUint32)m_context.getBinaryCollection().get(sourceName).getSize();
253 
254 	const VkShaderModuleCreateInfo moduleCreateInfo =
255 	{
256 		VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,				// VkStructureType				sType;
257 		DE_NULL,													// const void*					pNext;
258 		0u,															// VkShaderModuleCreateFlags	flags;
259 		codeSize,													// deUintptr					codeSize;
260 		code,														// const deUint32*				pCode;
261 	};
262 
263 	m_shaderModules[m_shaderStageCount] = createShaderModule(vk, vkDevice, &moduleCreateInfo);
264 
265 	// Prepare shader stage info
266 	m_shaderStageInfo[m_shaderStageCount].sType				= VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
267 	m_shaderStageInfo[m_shaderStageCount].pNext				= DE_NULL;
268 	m_shaderStageInfo[m_shaderStageCount].flags				= 0u;
269 	m_shaderStageInfo[m_shaderStageCount].stage				= stage;
270 	m_shaderStageInfo[m_shaderStageCount].module				= *m_shaderModules[m_shaderStageCount];
271 	m_shaderStageInfo[m_shaderStageCount].pName				= entryName;
272 	m_shaderStageInfo[m_shaderStageCount].pSpecializationInfo	= DE_NULL;
273 
274 	m_shaderStageCount++;
275 }
276 
buildPipeline(tcu::UVec2 renderSize,VkRenderPass renderPass,VkPipelineCache cache,VkPipelineLayout pipelineLayout,VkPipelineCreationFeedbackEXT * pipelineCreationFeedback,VkPipelineCreationFeedbackEXT * pipelineStageCreationFeedbacks,VkPipeline basePipelineHandle)277 VkPipeline SimpleGraphicsPipelineBuilder::buildPipeline (tcu::UVec2 renderSize, VkRenderPass renderPass, VkPipelineCache cache,
278 														 VkPipelineLayout pipelineLayout, VkPipelineCreationFeedbackEXT *pipelineCreationFeedback,
279 														 VkPipelineCreationFeedbackEXT *pipelineStageCreationFeedbacks, VkPipeline basePipelineHandle)
280 {
281 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
282 	const VkDevice				vkDevice			= m_context.getDevice();
283 
284 	// Create pipeline
285 	const VkVertexInputBindingDescription vertexInputBindingDescription =
286 	{
287 		0u,									// deUint32				binding;
288 		sizeof(Vertex4RGBA),				// deUint32				strideInBytes;
289 		VK_VERTEX_INPUT_RATE_VERTEX,		// VkVertexInputRate	inputRate;
290 	};
291 
292 	const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
293 	{
294 		{
295 			0u,									// deUint32 location;
296 			0u,									// deUint32 binding;
297 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat format;
298 			0u									// deUint32 offsetInBytes;
299 		},
300 		{
301 			1u,									// deUint32 location;
302 			0u,									// deUint32 binding;
303 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat format;
304 			DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32 offsetInBytes;
305 		}
306 	};
307 
308 	const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
309 	{
310 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
311 		DE_NULL,														// const void*								pNext;
312 		0u,																// VkPipelineVertexInputStateCreateFlags	flags;
313 		1u,																// deUint32									vertexBindingDescriptionCount;
314 		&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
315 		2u,																// deUint32									vertexAttributeDescriptionCount;
316 		vertexInputAttributeDescriptions,								// const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
317 	};
318 
319 	const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateParams =
320 	{
321 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType							sType;
322 		DE_NULL,														// const void*								pNext;
323 		0u,																// VkPipelineInputAssemblyStateCreateFlags	flags;
324 		(m_patchControlPoints == 0 ? VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
325 								   : VK_PRIMITIVE_TOPOLOGY_PATCH_LIST), // VkPrimitiveTopology						topology;
326 		VK_FALSE,														// VkBool32									primitiveRestartEnable;
327 	};
328 
329 	const VkViewport	viewport	= makeViewport(renderSize);
330 	const VkRect2D		scissor	= makeRect2D(renderSize);
331 
332 	const VkPipelineViewportStateCreateInfo viewportStateParams =
333 	{
334 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,			// VkStructureType						sType;
335 		DE_NULL,														// const void*							pNext;
336 		0u,																// VkPipelineViewportStateCreateFlags	flags;
337 		1u,																// deUint32								viewportCount;
338 		&viewport,														// const VkViewport*					pViewports;
339 		1u,																// deUint32								scissorCount;
340 		&scissor														// const VkRect2D*						pScissors;
341 	};
342 
343 	const VkPipelineRasterizationStateCreateInfo rasterStateParams =
344 	{
345 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// VkStructureType							sType;
346 		DE_NULL,														// const void*								pNext;
347 		0u,																// VkPipelineRasterizationStateCreateFlags	flags;
348 		VK_FALSE,														// VkBool32									depthClampEnable;
349 		VK_FALSE,														// VkBool32									rasterizerDiscardEnable;
350 		VK_POLYGON_MODE_FILL,											// VkPolygonMode							polygonMode;
351 		VK_CULL_MODE_NONE,												// VkCullModeFlags							cullMode;
352 		VK_FRONT_FACE_COUNTER_CLOCKWISE,								// VkFrontFace								frontFace;
353 		VK_FALSE,														// VkBool32									depthBiasEnable;
354 		0.0f,															// float									depthBiasConstantFactor;
355 		0.0f,															// float									depthBiasClamp;
356 		0.0f,															// float									depthBiasSlopeFactor;
357 		1.0f,															// float									lineWidth;
358 	};
359 
360 	const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
361 	{
362 		VK_FALSE,														// VkBool32		blendEnable;
363 		VK_BLEND_FACTOR_ONE,											// VkBlendFactor	srcColorBlendFactor;
364 		VK_BLEND_FACTOR_ZERO,											// VkBlendFactor	dstColorBlendFactor;
365 		VK_BLEND_OP_ADD,												// VkBlendOp		colorBlendOp;
366 		VK_BLEND_FACTOR_ONE,											// VkBlendFactor	srcAlphaBlendFactor;
367 		VK_BLEND_FACTOR_ZERO,											// VkBlendFactor	dstAlphaBlendFactor;
368 		VK_BLEND_OP_ADD,												// VkBlendOp		alphaBlendOp;
369 		VK_COLOR_COMPONENT_R_BIT |
370 		VK_COLOR_COMPONENT_G_BIT |
371 		VK_COLOR_COMPONENT_B_BIT |
372 		VK_COLOR_COMPONENT_A_BIT										// VkColorComponentFlags    colorWriteMask;
373 	};
374 
375 	const VkPipelineColorBlendStateCreateInfo colorBlendStateParams =
376 	{
377 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
378 		DE_NULL,													// const void*									pNext;
379 		0u,															// VkPipelineColorBlendStateCreateFlags			flags;
380 		VK_FALSE,													// VkBool32										logicOpEnable;
381 		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
382 		1u,															// deUint32										attachmentCount;
383 		&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
384 		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
385 	};
386 
387 	const VkPipelineMultisampleStateCreateInfo  multisampleStateParams	=
388 	{
389 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	// VkStructureType							sType;
390 		DE_NULL,													// const void*								pNext;
391 		0u,															// VkPipelineMultisampleStateCreateFlags	flags;
392 		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits					rasterizationSamples;
393 		VK_FALSE,													// VkBool32									sampleShadingEnable;
394 		0.0f,														// float									minSampleShading;
395 		DE_NULL,													// const VkSampleMask*						pSampleMask;
396 		VK_FALSE,													// VkBool32									alphaToCoverageEnable;
397 		VK_FALSE,													// VkBool32									alphaToOneEnable;
398 	};
399 
400 	VkPipelineDepthStencilStateCreateInfo depthStencilStateParams =
401 	{
402 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType							sType;
403 		DE_NULL,													// const void*								pNext;
404 		0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
405 		VK_TRUE,													// VkBool32									depthTestEnable;
406 		VK_TRUE,													// VkBool32									depthWriteEnable;
407 		VK_COMPARE_OP_LESS_OR_EQUAL,								// VkCompareOp								depthCompareOp;
408 		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
409 		VK_FALSE,													// VkBool32									stencilTestEnable;
410 		// VkStencilOpState front;
411 		{
412 			VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
413 			VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
414 			VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
415 			VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
416 			0u,						// deUint32		compareMask;
417 			0u,						// deUint32		writeMask;
418 			0u,						// deUint32		reference;
419 		},
420 		// VkStencilOpState back;
421 		{
422 			VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
423 			VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
424 			VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
425 			VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
426 			0u,						// deUint32		compareMask;
427 			0u,						// deUint32		writeMask;
428 			0u,						// deUint32		reference;
429 		},
430 		0.0f,														// float									minDepthBounds;
431 		1.0f,														// float									maxDepthBounds;
432 	};
433 
434 	const VkPipelineTessellationStateCreateInfo tessStateCreateInfo =
435 	{
436 		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,	// VkStructureType							sType;
437 		DE_NULL,													// const void*								pNext;
438 		0u,															// VkPipelineTesselationStateCreateFlags	flags;
439 		m_patchControlPoints,										// deUint32									patchControlPoints;
440 	};
441 	const VkPipelineTessellationStateCreateInfo* pTessCreateInfo = (m_patchControlPoints > 0)
442 																  ? &tessStateCreateInfo
443 																  : DE_NULL;
444 
445 	const VkPipelineCreationFeedbackCreateInfoEXT pipelineCreationFeedbackCreateInfo =
446 	{
447 		VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT,	// VkStructureType						sType;
448 		DE_NULL,														// const void*							pNext;
449 		pipelineCreationFeedback,										// VkPipelineCreationFeedbackEXT*		pPipelineCreationFeedback;
450 		m_shaderStageCount,												// deUint32								pipelineStageCreationFeedbackCount;
451 		pipelineStageCreationFeedbacks									// VkPipelineCreationFeedbackEXT*		pPipelineStageCreationFeedbacks;
452 	};
453 
454 	deUint32 flagsCreateInfo = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT;
455 	if (basePipelineHandle != DE_NULL)
456 	{
457 		flagsCreateInfo = VK_PIPELINE_CREATE_DERIVATIVE_BIT;
458 	}
459 
460 	const VkGraphicsPipelineCreateInfo graphicsPipelineParams =
461 	{
462 		VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,	// VkStructureType									sType;
463 		&pipelineCreationFeedbackCreateInfo,				// const void*										pNext;
464 		flagsCreateInfo,									// VkPipelineCreateFlags							flags;
465 		m_shaderStageCount,									// deUint32											stageCount;
466 		m_shaderStageInfo,									// const VkPipelineShaderStageCreateInfo*			pStages;
467 		&vertexInputStateParams,							// const VkPipelineVertexInputStateCreateInfo*		pVertexInputState;
468 		&inputAssemblyStateParams,							// const VkPipelineInputAssemblyStateCreateInfo*	pInputAssemblyState;
469 		pTessCreateInfo,									// const VkPipelineTessellationStateCreateInfo*		pTessellationState;
470 		&viewportStateParams,								// const VkPipelineViewportStateCreateInfo*			pViewportState;
471 		&rasterStateParams,									// const VkPipelineRasterizationStateCreateInfo*	pRasterState;
472 		&multisampleStateParams,							// const VkPipelineMultisampleStateCreateInfo*		pMultisampleState;
473 		&depthStencilStateParams,							// const VkPipelineDepthStencilStateCreateInfo*		pDepthStencilState;
474 		&colorBlendStateParams,								// const VkPipelineColorBlendStateCreateInfo*		pColorBlendState;
475 		(const VkPipelineDynamicStateCreateInfo*)DE_NULL,	// const VkPipelineDynamicStateCreateInfo*			pDynamicState;
476 		pipelineLayout,										// VkPipelineLayout									layout;
477 		renderPass,											// VkRenderPass										renderPass;
478 		0u,													// deUint32											subpass;
479 		basePipelineHandle,									// VkPipeline										basePipelineHandle;
480 		basePipelineHandle != DE_NULL ? -1 : 0,				// deInt32											basePipelineIndex;
481 	};
482 	VkPipeline pipeline;
483 	vk.createGraphicsPipelines(vkDevice, cache, 1u, &graphicsPipelineParams, DE_NULL, &pipeline);
484 	return pipeline;
485 }
486 
enableTessellationStage(deUint32 patchControlPoints)487 void SimpleGraphicsPipelineBuilder::enableTessellationStage (deUint32 patchControlPoints)
488 {
489 	m_patchControlPoints = patchControlPoints;
490 }
491 
492 template <class Test>
newTestCase(tcu::TestContext & testContext,const CacheTestParam * testParam)493 vkt::TestCase* newTestCase (tcu::TestContext&		testContext,
494 							const CacheTestParam*	testParam)
495 {
496 	return new Test(testContext,
497 					testParam->generateTestName().c_str(),
498 					testParam->generateTestDescription().c_str(),
499 					testParam);
500 }
501 
502 // Test Classes
503 class CacheTest : public vkt::TestCase
504 {
505 public:
CacheTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const CacheTestParam * param)506 							CacheTest(tcu::TestContext&		testContext,
507 									  const std::string&		name,
508 									  const std::string&		description,
509 									  const CacheTestParam*	param)
510 								: vkt::TestCase (testContext, name, description)
511 								, m_param (*param)
512 								{ }
~CacheTest(void)513 	virtual				~CacheTest (void) { }
514 protected:
515 	const CacheTestParam	m_param;
516 };
517 
518 class CacheTestInstance : public vkt::TestInstance
519 {
520 public:
521 							CacheTestInstance			(Context&				context,
522 														 const CacheTestParam*	param);
523 	virtual					~CacheTestInstance			(void);
524 	virtual tcu::TestStatus iterate						(void);
525 protected:
526 	virtual tcu::TestStatus verifyTestResult			(void) = 0;
527 protected:
528 	const CacheTestParam*	m_param;
529 
530 	Move<VkPipelineCache>	m_cache;
531 	deBool					m_extensions;
532 };
533 
CacheTestInstance(Context & context,const CacheTestParam * param)534 CacheTestInstance::CacheTestInstance (Context&					context,
535 									  const CacheTestParam*	param)
536 	: TestInstance		(context)
537 	, m_param			(param)
538 	, m_extensions		(m_context.requireDeviceFunctionality("VK_EXT_pipeline_creation_feedback"))
539 {
540 	const DeviceInterface&	vk				= m_context.getDeviceInterface();
541 	const VkDevice			vkDevice		= m_context.getDevice();
542 
543 	if (m_param->isCacheDisabled() == DE_FALSE)
544 	{
545 		const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
546 		{
547 			VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,			// VkStructureType				sType;
548 			DE_NULL,												// const void*					pNext;
549 			0u,														// VkPipelineCacheCreateFlags	flags;
550 			0u,														// deUintptr					initialDataSize;
551 			DE_NULL,												// const void*					pInitialData;
552 		};
553 
554 		m_cache = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
555 	}
556 }
557 
~CacheTestInstance(void)558 CacheTestInstance::~CacheTestInstance (void)
559 {
560 }
561 
iterate(void)562 tcu::TestStatus CacheTestInstance::iterate (void)
563 {
564 	return verifyTestResult();
565 }
566 
567 class GraphicsCacheTest : public CacheTest
568 {
569 public:
GraphicsCacheTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const CacheTestParam * param)570 							GraphicsCacheTest	(tcu::TestContext&		testContext,
571 												 const std::string&		name,
572 												 const std::string&		description,
573 												 const CacheTestParam*	param)
574 								: CacheTest (testContext, name, description, param)
575 								{ }
~GraphicsCacheTest(void)576 	virtual					~GraphicsCacheTest	(void) { }
577 	virtual void			initPrograms		(SourceCollections&	programCollection) const;
578 	virtual void			checkSupport		(Context&			context) const;
579 	virtual TestInstance*	createInstance		(Context&			context) const;
580 };
581 
582 class GraphicsCacheTestInstance : public CacheTestInstance
583 {
584 public:
585 							GraphicsCacheTestInstance	(Context&				context,
586 														 const CacheTestParam*	param);
587 	virtual					~GraphicsCacheTestInstance	(void);
588 protected:
589 	virtual tcu::TestStatus verifyTestResult			(void);
590 
591 protected:
592 	const tcu::UVec2					m_renderSize;
593 	const VkFormat						m_colorFormat;
594 	const VkFormat						m_depthFormat;
595 	Move<VkPipelineLayout>				m_pipelineLayout;
596 
597 	SimpleGraphicsPipelineBuilder		m_pipelineBuilder;
598 	SimpleGraphicsPipelineBuilder		m_missPipelineBuilder;
599 	Move<VkRenderPass>					m_renderPass;
600 
601 	VkPipeline							m_pipeline[PIPELINE_CACHE_NDX_COUNT];
602 	VkPipelineCreationFeedbackEXT		m_pipelineCreationFeedback[PIPELINE_CACHE_NDX_COUNT];
603 	VkPipelineCreationFeedbackEXT		m_pipelineStageCreationFeedbacks[PIPELINE_CACHE_NDX_COUNT * VK_MAX_SHADER_STAGES];
604 };
605 
initPrograms(SourceCollections & programCollection) const606 void GraphicsCacheTest::initPrograms (SourceCollections& programCollection) const
607 {
608 	for (deUint32 shaderNdx = 0; shaderNdx < m_param.getShaderCount(); shaderNdx++)
609 	{
610 		switch(m_param.getShaderFlag(shaderNdx))
611 		{
612 		case VK_SHADER_STAGE_VERTEX_BIT:
613 			programCollection.glslSources.add("color_vert_1") << glu::VertexSource(
614 						"#version 310 es\n"
615 						"layout(location = 0) in vec4 position;\n"
616 						"layout(location = 1) in vec4 color;\n"
617 						"layout(location = 0) out highp vec4 vtxColor;\n"
618 						"void main (void)\n"
619 						"{\n"
620 						"  gl_Position = position;\n"
621 						"  vtxColor = color;\n"
622 						"}\n");
623 			programCollection.glslSources.add("color_vert_2") << glu::VertexSource(
624 						"#version 310 es\n"
625 						"layout(location = 0) in vec4 position;\n"
626 						"layout(location = 1) in vec4 color;\n"
627 						"layout(location = 0) out highp vec4 vtxColor;\n"
628 						"void main (void)\n"
629 						"{\n"
630 						"  gl_Position = position;\n"
631 						"  gl_PointSize = 1.0f;\n"
632 						"  vtxColor = color + vec4(0.1, 0.2, 0.3, 0.0);\n"
633 						"}\n");
634 					break;
635 		case VK_SHADER_STAGE_FRAGMENT_BIT:
636 			programCollection.glslSources.add("color_frag") << glu::FragmentSource(
637 						"#version 310 es\n"
638 						"layout(location = 0) in highp vec4 vtxColor;\n"
639 						"layout(location = 0) out highp vec4 fragColor;\n"
640 						"void main (void)\n"
641 						"{\n"
642 						"  fragColor = vtxColor;\n"
643 						"}\n");
644 			break;
645 
646 		case VK_SHADER_STAGE_GEOMETRY_BIT:
647 			programCollection.glslSources.add("dummy_geo") << glu::GeometrySource(
648 						"#version 450 \n"
649 						"layout(triangles) in;\n"
650 						"layout(triangle_strip, max_vertices = 3) out;\n"
651 						"layout(location = 0) in highp vec4 in_vtxColor[];\n"
652 						"layout(location = 0) out highp vec4 vtxColor;\n"
653 						"out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };\n"
654 						"in gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_in[];\n"
655 						"void main (void)\n"
656 						"{\n"
657 						"  for(int ndx=0; ndx<3; ndx++)\n"
658 						"  {\n"
659 						"    gl_Position = gl_in[ndx].gl_Position;\n"
660 						"    gl_PointSize = gl_in[ndx].gl_PointSize;\n"
661 						"    vtxColor    = in_vtxColor[ndx];\n"
662 						"    EmitVertex();\n"
663 						"  }\n"
664 						"  EndPrimitive();\n"
665 						"}\n");
666 			break;
667 
668 		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
669 			programCollection.glslSources.add("basic_tcs") << glu::TessellationControlSource(
670 						"#version 450 \n"
671 						"layout(vertices = 3) out;\n"
672 						"layout(location = 0) in highp vec4 color[];\n"
673 						"layout(location = 0) out highp vec4 vtxColor[];\n"
674 						"out gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_out[3];\n"
675 						"in gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_in[gl_MaxPatchVertices];\n"
676 						"void main()\n"
677 						"{\n"
678 						"  gl_TessLevelOuter[0] = 4.0;\n"
679 						"  gl_TessLevelOuter[1] = 4.0;\n"
680 						"  gl_TessLevelOuter[2] = 4.0;\n"
681 						"  gl_TessLevelInner[0] = 4.0;\n"
682 						"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
683 						"  gl_out[gl_InvocationID].gl_PointSize = gl_in[gl_InvocationID].gl_PointSize;\n"
684 						"  vtxColor[gl_InvocationID] = color[gl_InvocationID];\n"
685 						"}\n");
686 					break;
687 
688 				case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
689 					programCollection.glslSources.add("basic_tes") << glu::TessellationEvaluationSource(
690 						"#version 450 \n"
691 						"layout(triangles, fractional_even_spacing, ccw) in;\n"
692 						"layout(location = 0) in highp vec4 colors[];\n"
693 						"layout(location = 0) out highp vec4 vtxColor;\n"
694 						"out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };\n"
695 						"in gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_in[gl_MaxPatchVertices];\n"
696 						"void main() \n"
697 						"{\n"
698 						"  float u = gl_TessCoord.x;\n"
699 						"  float v = gl_TessCoord.y;\n"
700 						"  float w = gl_TessCoord.z;\n"
701 						"  vec4 pos = vec4(0);\n"
702 						"  vec4 color = vec4(0);\n"
703 						"  pos.xyz += u * gl_in[0].gl_Position.xyz;\n"
704 						"  color.xyz += u * colors[0].xyz;\n"
705 						"  pos.xyz += v * gl_in[1].gl_Position.xyz;\n"
706 						"  color.xyz += v * colors[1].xyz;\n"
707 						"  pos.xyz += w * gl_in[2].gl_Position.xyz;\n"
708 						"  color.xyz += w * colors[2].xyz;\n"
709 						"  pos.w = 1.0;\n"
710 						"  color.w = 1.0;\n"
711 						"  gl_Position = pos;\n"
712 						"  gl_PointSize = gl_in[0].gl_PointSize;"
713 						"  vtxColor = color;\n"
714 						"}\n");
715 					break;
716 
717 				default:
718 					DE_FATAL("Unknown Shader Stage!");
719 					break;
720 		}
721 	}
722 }
723 
checkSupport(Context & context) const724 void GraphicsCacheTest::checkSupport (Context& context) const
725 {
726 	for (deUint32 shaderNdx = 0; shaderNdx < m_param.getShaderCount(); shaderNdx++)
727 	{
728 		switch(m_param.getShaderFlag(shaderNdx))
729 		{
730 		case VK_SHADER_STAGE_GEOMETRY_BIT:
731 			context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
732 			break;
733 		case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
734 		case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
735 			context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
736 			break;
737 		default:
738 			break;
739 		}
740 	}
741 }
742 
createInstance(Context & context) const743 TestInstance* GraphicsCacheTest::createInstance (Context& context) const
744 {
745 	return new GraphicsCacheTestInstance(context, &m_param);
746 }
747 
GraphicsCacheTestInstance(Context & context,const CacheTestParam * param)748 GraphicsCacheTestInstance::GraphicsCacheTestInstance (Context&				context,
749 													  const CacheTestParam*	param)
750 	: CacheTestInstance		(context, param)
751 	, m_renderSize			(32u, 32u)
752 	, m_colorFormat			(VK_FORMAT_R8G8B8A8_UNORM)
753 	, m_depthFormat			(VK_FORMAT_D16_UNORM)
754 	, m_pipelineBuilder		(context)
755 	, m_missPipelineBuilder	(context)
756 {
757 	const DeviceInterface&	vk				= m_context.getDeviceInterface();
758 	const VkDevice			vkDevice		= m_context.getDevice();
759 
760 	// Create pipeline layout
761 	{
762 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
763 		{
764 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
765 			DE_NULL,											// const void*						pNext;
766 			0u,													// VkPipelineLayoutCreateFlags		flags;
767 			0u,													// deUint32							setLayoutCount;
768 			DE_NULL,											// const VkDescriptorSetLayout*		pSetLayouts;
769 			0u,													// deUint32							pushConstantRangeCount;
770 			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
771 		};
772 
773 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
774 	}
775 
776 	// Create render pass
777 	m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat, m_depthFormat);
778 
779 	// Bind shader stages
780 	for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
781 	{
782 		for (deUint32 shaderNdx = 0; shaderNdx < m_param->getShaderCount(); shaderNdx++)
783 		{
784 			switch(m_param->getShaderFlag(shaderNdx))
785 			{
786 			case VK_SHADER_STAGE_VERTEX_BIT:
787 				{
788 					std::string	shader_name("color_vert_");
789 					shader_name += (ndx == PIPELINE_CACHE_NDX_DERIVATIVE) ? "2" : "1";
790 					m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_VERTEX_BIT, shader_name.c_str(), "main");
791 				}
792 				break;
793 			case VK_SHADER_STAGE_FRAGMENT_BIT:
794 				m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_FRAGMENT_BIT, "color_frag", "main");
795 				break;
796 			case VK_SHADER_STAGE_GEOMETRY_BIT:
797 				m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_GEOMETRY_BIT, "dummy_geo", "main");
798 				break;
799 			case VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT:
800 				m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, "basic_tcs", "main");
801 				m_pipelineBuilder.enableTessellationStage(3);
802 				break;
803 			case VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT:
804 				m_pipelineBuilder.bindShaderStage(VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, "basic_tes", "main");
805 				m_pipelineBuilder.enableTessellationStage(3);
806 				break;
807 			default:
808 				DE_FATAL("Unknown Shader Stage!");
809 				break;
810 			}
811 		}
812 		if (ndx == PIPELINE_CACHE_NDX_CACHED && !param->isDelayedDestroy())
813 		{
814 			// Destroy the NO_CACHE pipeline to check that the cached one really hits cache,
815 			// except for the case where we're testing cache hit of a pipeline still active.
816 			vk.destroyPipeline(vkDevice, m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], DE_NULL);
817 		}
818 
819 		m_pipeline[ndx] = m_pipelineBuilder.buildPipeline(m_renderSize, *m_renderPass, *m_cache, *m_pipelineLayout,
820 														  &m_pipelineCreationFeedback[ndx],
821 														  &m_pipelineStageCreationFeedbacks[VK_MAX_SHADER_STAGES * ndx],
822 														  ndx == PIPELINE_CACHE_NDX_DERIVATIVE ? m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE] : DE_NULL);
823 		m_pipelineBuilder.resetBuilder();
824 
825 		if (ndx != PIPELINE_CACHE_NDX_NO_CACHE)
826 		{
827 			// Destroy the pipeline as soon as it is created, except the NO_CACHE because
828 			// it is needed as a base pipeline for the derivative case.
829 			vk.destroyPipeline(vkDevice, m_pipeline[ndx], DE_NULL);
830 
831 			if (ndx == PIPELINE_CACHE_NDX_CACHED && param->isDelayedDestroy())
832 			{
833 				// Destroy the pipeline we didn't destroy earlier for the isDelayedDestroy case.
834 				vk.destroyPipeline(vkDevice, m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], DE_NULL);
835 			}
836 	}
837 	}
838 }
839 
~GraphicsCacheTestInstance(void)840 GraphicsCacheTestInstance::~GraphicsCacheTestInstance (void)
841 {
842 }
843 
verifyTestResult(void)844 tcu::TestStatus GraphicsCacheTestInstance::verifyTestResult (void)
845 {
846 	tcu::TestLog &log			= m_context.getTestContext().getLog();
847 	bool durationZeroWarning	= DE_FALSE;
848 	bool cachedPipelineWarning	= DE_FALSE;
849 
850 	for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
851 	{
852 		std::ostringstream	message;
853 		message << getCaseStr(ndx);
854 
855 		// No need to check per stage status as it is compute pipeline (only one stage) and Vulkan spec mentions that:
856 		// "One common scenario for an implementation to skip per-stage feedback is when
857 		// VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT is set in pPipelineCreationFeedback."
858 		//
859 		// Check first that the no cached pipeline was missed in the pipeline cache
860 		if (!(m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT))
861 		{
862 			message << ": invalid data";
863 			return tcu::TestStatus::fail(message.str());
864 		}
865 
866 		if (m_param->isCacheDisabled() && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT)
867 		{
868 			message << ": feedback indicates pipeline hit cache when it shouldn't";
869 			return tcu::TestStatus::fail(message.str());
870 		}
871 
872 		if (ndx == PIPELINE_CACHE_NDX_NO_CACHE && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT)
873 		{
874 			message << ": hit the cache when it shouldn't";
875 			return tcu::TestStatus::fail(message.str());
876 		}
877 
878 		if (ndx != PIPELINE_CACHE_NDX_DERIVATIVE && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT)
879 		{
880 			message << ": feedback indicates base pipeline acceleration when it shouldn't";
881 			return tcu::TestStatus::fail(message.str());
882 		}
883 
884 		if (ndx == PIPELINE_CACHE_NDX_CACHED && !m_param->isCacheDisabled() && (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) == 0)
885 		{
886 			message << "\nWarning: Cached pipeline case did not hit the cache";
887 			cachedPipelineWarning = DE_TRUE;
888 		}
889 
890 		if (m_pipelineCreationFeedback[ndx].duration == 0)
891 		{
892 			message << "\nWarning: Pipeline creation feedback reports duration spent creating a pipeline was zero nanoseconds\n";
893 			durationZeroWarning = DE_TRUE;
894 		}
895 
896 		message << "\n";
897 		message << "\t\t Hit cache ? \t\t\t"				<< (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT ? "yes" : "no")	<< "\n";
898 		message << "\t\t Base Pipeline Acceleration ? \t"	<< (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT ?	 "yes" : "no")		<< "\n";
899 		message << "\t\t Duration (ns): \t\t"				<< m_pipelineCreationFeedback[ndx].duration																							<< "\n";
900 
901 		for(deUint32 shader = 0; shader < m_param->getShaderCount(); shader++)
902 		{
903 			const deUint32 index = VK_MAX_SHADER_STAGES * ndx + shader;
904 			message << "\t" << getShaderFlagStr(m_param->getShaderFlag(shader), true) << "\n";
905 
906 			if (!(m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT))
907 			{
908 				if (m_pipelineStageCreationFeedbacks[index].flags)
909 				{
910 					std::ostringstream			errorMsg;
911 					errorMsg << getCaseStr(ndx) << ": Creation feedback is not valid for " + getShaderFlagStr(m_param->getShaderFlag(shader), true) + " but there are other flags written";
912 					return tcu::TestStatus::fail(errorMsg.str());
913 				}
914 				message << "\t\t Pipeline Creation Feedback data is not valid\n";
915 				continue;
916 			}
917 			if (m_param->isCacheDisabled() && m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT)
918 			{
919 				std::ostringstream			errorMsg;
920 				errorMsg << getCaseStr(ndx) << ": feedback indicates pipeline " + getShaderFlagStr(m_param->getShaderFlag(shader), true) + " stage hit cache when it shouldn't";
921 				return tcu::TestStatus::fail(errorMsg.str());
922 			}
923 
924 			if (ndx == PIPELINE_CACHE_NDX_CACHED && !m_param->isCacheDisabled() && (m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) == 0)
925 			{
926 				message << "Warning: pipeline stage did not hit the cache\n";
927 				cachedPipelineWarning = DE_TRUE;
928 			}
929 			if (cachedPipelineWarning && m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT)
930 			{
931 				// We only set the warning when the pipeline nor the pipeline stages hit the cache. If any of them did, them disable the warning.
932 				cachedPipelineWarning = DE_FALSE;
933 			}
934 
935 			message << "\t\t Hit cache ? \t\t\t"				<< (m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT ? "yes" : "no")	<< "\n";
936 			message << "\t\t Base Pipeline Acceleration ? \t"	<< (m_pipelineStageCreationFeedbacks[index].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT ?	 "yes" : "no")		<< "\n";
937 			message << "\t\t Duration (ns): \t\t"				<< m_pipelineStageCreationFeedbacks[index].duration																							<< "\n";
938 		}
939 
940 		log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
941 	}
942 
943 	if (cachedPipelineWarning)
944 	{
945 		return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Cached pipeline or stage did not hit the cache");
946 	}
947 	if (durationZeroWarning)
948 	{
949 		return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Pipeline creation feedback reports duration spent creating a pipeline was zero nanoseconds");
950 	}
951 	return tcu::TestStatus::pass("Pass");
952 }
953 
954 class ComputeCacheTest : public CacheTest
955 {
956 public:
ComputeCacheTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const CacheTestParam * param)957 							ComputeCacheTest		(tcu::TestContext&		testContext,
958 													 const std::string&		name,
959 													 const std::string&		description,
960 													 const CacheTestParam*	param)
961 								: CacheTest		(testContext, name, description, param)
962 								{ }
~ComputeCacheTest(void)963 	virtual					~ComputeCacheTest	(void) { }
964 	virtual void			initPrograms			(SourceCollections&	programCollection) const;
965 	virtual TestInstance*	createInstance			(Context&				context) const;
966 };
967 
968 class ComputeCacheTestInstance : public CacheTestInstance
969 {
970 public:
971 							ComputeCacheTestInstance		(Context&				context,
972 															 const CacheTestParam*	param);
973 	virtual					~ComputeCacheTestInstance	(void);
974 protected:
975 	virtual tcu::TestStatus verifyTestResult				(void);
976 			void			buildDescriptorSets				(deUint32 ndx);
977 			void			buildShader						(deUint32 ndx);
978 			void			buildPipeline					(const CacheTestParam*	param, deUint32 ndx);
979 protected:
980 	Move<VkBuffer>					m_inputBuf;
981 	de::MovePtr<Allocation>		m_inputBufferAlloc;
982 	Move<VkShaderModule>			m_computeShaderModule[PIPELINE_CACHE_NDX_COUNT];
983 
984 	Move<VkBuffer>					m_outputBuf[PIPELINE_CACHE_NDX_COUNT];
985 	de::MovePtr<Allocation>		m_outputBufferAlloc[PIPELINE_CACHE_NDX_COUNT];
986 
987 	Move<VkDescriptorPool>			m_descriptorPool[PIPELINE_CACHE_NDX_COUNT];
988 	Move<VkDescriptorSetLayout>	m_descriptorSetLayout[PIPELINE_CACHE_NDX_COUNT];
989 	Move<VkDescriptorSet>			m_descriptorSet[PIPELINE_CACHE_NDX_COUNT];
990 
991 	Move<VkPipelineLayout>			m_pipelineLayout[PIPELINE_CACHE_NDX_COUNT];
992 	VkPipeline						m_pipeline[PIPELINE_CACHE_NDX_COUNT];
993 	VkPipelineCreationFeedbackEXT	m_pipelineCreationFeedback[PIPELINE_CACHE_NDX_COUNT];
994 	VkPipelineCreationFeedbackEXT	m_pipelineStageCreationFeedback[PIPELINE_CACHE_NDX_COUNT];
995 };
996 
initPrograms(SourceCollections & programCollection) const997 void ComputeCacheTest::initPrograms (SourceCollections& programCollection) const
998 {
999 	programCollection.glslSources.add("basic_compute_1") << glu::ComputeSource(
1000 		"#version 310 es\n"
1001 		"layout(local_size_x = 1) in;\n"
1002 		"layout(std430) buffer;\n"
1003 		"layout(binding = 0) readonly buffer Input0\n"
1004 		"{\n"
1005 		"  vec4 elements[];\n"
1006 		"} input_data0;\n"
1007 		"layout(binding = 1) writeonly buffer Output\n"
1008 		"{\n"
1009 		"  vec4 elements[];\n"
1010 		"} output_data;\n"
1011 		"void main()\n"
1012 		"{\n"
1013 		"  uint ident = gl_GlobalInvocationID.x;\n"
1014 		"  output_data.elements[ident] = input_data0.elements[ident] * input_data0.elements[ident];\n"
1015 		"}");
1016 	programCollection.glslSources.add("basic_compute_2") << glu::ComputeSource(
1017 		"#version 310 es\n"
1018 		"layout(local_size_x = 1) in;\n"
1019 		"layout(std430) buffer;\n"
1020 		"layout(binding = 0) readonly buffer Input0\n"
1021 		"{\n"
1022 		"  vec4 elements[];\n"
1023 		"} input_data0;\n"
1024 		"layout(binding = 1) writeonly buffer Output\n"
1025 		"{\n"
1026 		"  vec4 elements[];\n"
1027 		"} output_data;\n"
1028 		"void main()\n"
1029 		"{\n"
1030 		"  uint ident = gl_GlobalInvocationID.x;\n"
1031 		"  output_data.elements[ident] = input_data0.elements[ident];\n"
1032 		"}");
1033 }
1034 
createInstance(Context & context) const1035 TestInstance* ComputeCacheTest::createInstance (Context& context) const
1036 {
1037 	return new ComputeCacheTestInstance(context, &m_param);
1038 }
1039 
buildDescriptorSets(deUint32 ndx)1040 void ComputeCacheTestInstance::buildDescriptorSets (deUint32 ndx)
1041 {
1042 	const DeviceInterface&	vk				= m_context.getDeviceInterface();
1043 	const VkDevice			vkDevice		= m_context.getDevice();
1044 
1045 	// Create descriptor set layout
1046 	DescriptorSetLayoutBuilder descLayoutBuilder;
1047 	for (deUint32 bindingNdx = 0u; bindingNdx < 2u; bindingNdx++)
1048 		descLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
1049 	m_descriptorSetLayout[ndx] = descLayoutBuilder.build(vk, vkDevice);
1050 }
1051 
buildShader(deUint32 ndx)1052 void ComputeCacheTestInstance::buildShader (deUint32 ndx)
1053 {
1054 	const DeviceInterface&	vk				= m_context.getDeviceInterface();
1055 	const VkDevice			vkDevice		= m_context.getDevice();
1056 
1057 	std::string shader_name("basic_compute_");
1058 
1059 	shader_name += (ndx == PIPELINE_CACHE_NDX_DERIVATIVE) ? "2" : "1";
1060 
1061 	// Create compute shader
1062 	VkShaderModuleCreateInfo shaderModuleCreateInfo =
1063 	{
1064 		VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,								// VkStructureType				sType;
1065 		DE_NULL,																	// const void*					pNext;
1066 		0u,																		// VkShaderModuleCreateFlags	flags;
1067 		m_context.getBinaryCollection().get(shader_name).getSize(),				// deUintptr					codeSize;
1068 		(deUint32*)m_context.getBinaryCollection().get(shader_name).getBinary(),	// const deUint32*				pCode;
1069 	};
1070 	m_computeShaderModule[ndx] = createShaderModule(vk, vkDevice, &shaderModuleCreateInfo);
1071 }
1072 
buildPipeline(const CacheTestParam * param,deUint32 ndx)1073 void ComputeCacheTestInstance::buildPipeline (const CacheTestParam*	param, deUint32 ndx)
1074 {
1075 	const DeviceInterface&	vk				 = m_context.getDeviceInterface();
1076 	const VkDevice			vkDevice		 = m_context.getDevice();
1077 
1078 	deMemset(&m_pipelineCreationFeedback[ndx], 0, sizeof(VkPipelineCreationFeedbackEXT));
1079 	deMemset(&m_pipelineStageCreationFeedback[ndx], 0, sizeof(VkPipelineCreationFeedbackEXT));
1080 
1081 	const VkPipelineCreationFeedbackCreateInfoEXT pipelineCreationFeedbackCreateInfo =
1082 	{
1083 		VK_STRUCTURE_TYPE_PIPELINE_CREATION_FEEDBACK_CREATE_INFO_EXT,	// VkStructureType					sType;
1084 		DE_NULL,														// const void *						pNext;
1085 		&m_pipelineCreationFeedback[ndx],								// VkPipelineCreationFeedbackEXT*	pPipelineCreationFeedback;
1086 		1u,															// deUint32						pipelineStageCreationFeedbackCount;
1087 		&m_pipelineStageCreationFeedback[ndx]							// VkPipelineCreationFeedbackEXT*	pPipelineStageCreationFeedbacks;
1088 	};
1089 
1090 	// Create compute pipeline layout
1091 	const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1092 	{
1093 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,					// VkStructureType					sType;
1094 		DE_NULL,														// const void*						pNext;
1095 		0u,															// VkPipelineLayoutCreateFlags		flags;
1096 		1u,															// deUint32						setLayoutCount;
1097 		&m_descriptorSetLayout[ndx].get(),								// const VkDescriptorSetLayout*	pSetLayouts;
1098 		0u,															// deUint32						pushConstantRangeCount;
1099 		DE_NULL,														// const VkPushConstantRange*		pPushConstantRanges;
1100 	};
1101 
1102 	m_pipelineLayout[ndx] = createPipelineLayout(vk, vkDevice, &pipelineLayoutCreateInfo);
1103 
1104 	const VkPipelineShaderStageCreateInfo stageCreateInfo =
1105 	{
1106 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,			// VkStructureType					sType;
1107 		DE_NULL,														// const void*						pNext;
1108 		0u,															// VkPipelineShaderStageCreateFlags	flags;
1109 		VK_SHADER_STAGE_COMPUTE_BIT,									// VkShaderStageFlagBits				stage;
1110 		*m_computeShaderModule[ndx],									// VkShaderModule						module;
1111 		"main",														// const char*						pName;
1112 		DE_NULL,														// const VkSpecializationInfo*		pSpecializationInfo;
1113 	};
1114 
1115 	VkComputePipelineCreateInfo pipelineCreateInfo =
1116 	{
1117 		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,				// VkStructureType					sType;
1118 		&pipelineCreationFeedbackCreateInfo,							// const void*						pNext;
1119 		0u,															// VkPipelineCreateFlags			flags;
1120 		stageCreateInfo,												// VkPipelineShaderStageCreateInfo	stage;
1121 		*m_pipelineLayout[ndx],										// VkPipelineLayout				layout;
1122 		(VkPipeline)0,													// VkPipeline						basePipelineHandle;
1123 		0u,															// deInt32							basePipelineIndex;
1124 	};
1125 
1126 	if (ndx != PIPELINE_CACHE_NDX_DERIVATIVE)
1127 	{
1128 		pipelineCreateInfo.flags = VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT;
1129 	}
1130 
1131 	if (ndx == PIPELINE_CACHE_NDX_DERIVATIVE)
1132 	{
1133 		pipelineCreateInfo.flags = VK_PIPELINE_CREATE_DERIVATIVE_BIT;
1134 		pipelineCreateInfo.basePipelineHandle = m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE];
1135 		pipelineCreateInfo.basePipelineIndex = -1;
1136 	}
1137 
1138 	if (ndx == PIPELINE_CACHE_NDX_CACHED && !param->isDelayedDestroy())
1139 	{
1140 		// Destroy the NO_CACHE pipeline to check that the cached one really hits cache,
1141 		// except for the case where we're testing cache hit of a pipeline still active.
1142 		vk.destroyPipeline(vkDevice, m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], DE_NULL);
1143 	}
1144 
1145 	vk.createComputePipelines(vkDevice, *m_cache, 1u, &pipelineCreateInfo, DE_NULL, &m_pipeline[ndx]);
1146 
1147 	if (ndx != PIPELINE_CACHE_NDX_NO_CACHE)
1148 	{
1149 		// Destroy the pipeline as soon as it is created, except the NO_CACHE because
1150 		// it is needed as a base pipeline for the derivative case.
1151 		vk.destroyPipeline(vkDevice, m_pipeline[ndx], DE_NULL);
1152 
1153 		if (ndx == PIPELINE_CACHE_NDX_CACHED && param->isDelayedDestroy())
1154 		{
1155 			// Destroy the pipeline we didn't destroy earlier for the isDelayedDestroy case.
1156 			vk.destroyPipeline(vkDevice, m_pipeline[PIPELINE_CACHE_NDX_NO_CACHE], DE_NULL);
1157 		}
1158 	}
1159 }
1160 
ComputeCacheTestInstance(Context & context,const CacheTestParam * param)1161 ComputeCacheTestInstance::ComputeCacheTestInstance (Context&				context,
1162 													const CacheTestParam*	param)
1163 	: CacheTestInstance (context, param)
1164 {
1165 	for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
1166 	{
1167 		buildDescriptorSets(ndx);
1168 		buildShader(ndx);
1169 		buildPipeline(param, ndx);
1170 	}
1171 }
1172 
~ComputeCacheTestInstance(void)1173 ComputeCacheTestInstance::~ComputeCacheTestInstance (void)
1174 {
1175 }
1176 
verifyTestResult(void)1177 tcu::TestStatus ComputeCacheTestInstance::verifyTestResult (void)
1178 {
1179 	tcu::TestLog &log				= m_context.getTestContext().getLog();
1180 	deBool durationZeroWarning		= DE_FALSE;
1181 	deBool cachedPipelineWarning	= DE_FALSE;
1182 
1183 	for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
1184 	{
1185 		std::ostringstream message;
1186 		message << getCaseStr(ndx);
1187 
1188 		// No need to check per stage status as it is compute pipeline (only one stage) and Vulkan spec mentions that:
1189 		// "One common scenario for an implementation to skip per-stage feedback is when
1190 		// VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT is set in pPipelineCreationFeedback."
1191 		//
1192 		// Check first that the no cached pipeline was missed in the pipeline cache
1193 		if (!(m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT))
1194 		{
1195 			message << ": invalid data";
1196 			return tcu::TestStatus::fail(message.str());
1197 		}
1198 
1199 		if (m_param->isCacheDisabled() && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT)
1200 		{
1201 			message << ": feedback indicates pipeline hit cache when it shouldn't";
1202 			return tcu::TestStatus::fail(message.str());
1203 		}
1204 
1205 		if (ndx == PIPELINE_CACHE_NDX_NO_CACHE && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT)
1206 		{
1207 			message << ": hit the cache when it shouldn't";
1208 			return tcu::TestStatus::fail(message.str());
1209 		}
1210 
1211 		if (!(ndx == PIPELINE_CACHE_NDX_DERIVATIVE && !m_param->isCacheDisabled()) && m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT)
1212 		{
1213 			message << ": feedback indicates base pipeline acceleration when it shouldn't";
1214 			return tcu::TestStatus::fail(message.str());
1215 		}
1216 
1217 		if (ndx == PIPELINE_CACHE_NDX_CACHED && !m_param->isCacheDisabled() && (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) == 0)
1218 		{
1219 			message << "\nWarning: Cached pipeline case did not hit the cache";
1220 			cachedPipelineWarning = DE_TRUE;
1221 		}
1222 
1223 		if (m_pipelineCreationFeedback[ndx].duration == 0)
1224 		{
1225 			message << "\nWarning: Pipeline creation feedback reports duration spent creating a pipeline was zero nanoseconds\n";
1226 			durationZeroWarning = DE_TRUE;
1227 		}
1228 
1229 		message << "\n";
1230 
1231 		message << "\t\t Hit cache ? \t\t\t"				<< (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT ? "yes" : "no")	<< "\n";
1232 		message << "\t\t Base Pipeline Acceleration ? \t"	<< (m_pipelineCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT ? "yes" : "no")		<< "\n";
1233 		message << "\t\t Duration (ns): \t\t"				<< m_pipelineCreationFeedback[ndx].duration																						<< "\n";
1234 
1235 		message << "\t Compute Stage\n";
1236 
1237 		// According to the spec:
1238 		//
1239 		// "An implementation should write pipeline creation feedback to pPipelineCreationFeedback and
1240 		//	may write pipeline stage creation feedback to pPipelineStageCreationFeedbacks."
1241 		if (!(m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT))
1242 		{
1243 			// According to the spec:
1244 			// "If the VK_PIPELINE_CREATION_FEEDBACK_VALID_BIT_EXT is not set in flags, an implementation
1245 			//	must not set any other bits in flags, and all other VkPipelineCreationFeedbackEXT data members are undefined."
1246 			if (m_pipelineStageCreationFeedback[ndx].flags)
1247 			{
1248 				std::ostringstream			errorMsg;
1249 				errorMsg << getCaseStr(ndx) << ": Creation feedback is not valid for compute stage but there are other flags written";
1250 				return tcu::TestStatus::fail(errorMsg.str());
1251 			}
1252 			message << "\t\t Pipeline Creation Feedback data is not valid\n";
1253 		}
1254 		else
1255 		{
1256 			if (m_param->isCacheDisabled() && m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT)
1257 			{
1258 				std::ostringstream			errorMsg;
1259 				errorMsg << getCaseStr(ndx) << ": feedback indicates pipeline compute stage hit cache when it shouldn't";
1260 				return tcu::TestStatus::fail(errorMsg.str());
1261 			}
1262 
1263 			if (ndx == PIPELINE_CACHE_NDX_CACHED && !m_param->isCacheDisabled() && (m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT) == 0)
1264 			{
1265 				message << "Warning: pipeline stage did not hit the cache\n";
1266 				cachedPipelineWarning = DE_TRUE;
1267 			}
1268 			if (cachedPipelineWarning && m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT)
1269 			{
1270 				// We only set the warning when the pipeline nor the pipeline stages hit the cache. If any of them did, them disable the warning.
1271 				cachedPipelineWarning = DE_FALSE;
1272 			}
1273 
1274 			message << "\t\t Hit cache ? \t\t\t"				<< (m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_APPLICATION_PIPELINE_CACHE_HIT_BIT_EXT ? "yes" : "no")	<< "\n";
1275 			message << "\t\t Base Pipeline Acceleration ? \t"	<< (m_pipelineStageCreationFeedback[ndx].flags & VK_PIPELINE_CREATION_FEEDBACK_BASE_PIPELINE_ACCELERATION_BIT_EXT ? "yes" : "no")		<< "\n";
1276 			message << "\t\t Duration (ns): \t\t"				<< m_pipelineStageCreationFeedback[ndx].duration																						<< "\n";
1277 		}
1278 
1279 		log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
1280 	}
1281 
1282 	if (cachedPipelineWarning)
1283 	{
1284 		return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Cached pipeline or stage did not hit the cache");
1285 	}
1286 	if (durationZeroWarning)
1287 	{
1288 		return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, "Pipeline creation feedback reports duration spent creating a pipeline was zero nanoseconds");
1289 	}
1290 	return tcu::TestStatus::pass("Pass");
1291 }
1292 } // anonymous
1293 
createCreationFeedbackTests(tcu::TestContext & testCtx)1294 tcu::TestCaseGroup* createCreationFeedbackTests (tcu::TestContext& testCtx)
1295 {
1296 	de::MovePtr<tcu::TestCaseGroup> cacheTests (new tcu::TestCaseGroup(testCtx, "creation_feedback", "pipeline creation feedback tests"));
1297 
1298 	// Graphics Pipeline Tests
1299 	{
1300 		de::MovePtr<tcu::TestCaseGroup> graphicsTests (new tcu::TestCaseGroup(testCtx, "graphics_tests", "Test pipeline creation feedback with graphics pipeline."));
1301 
1302 		const VkShaderStageFlagBits testParamShaders0[] =
1303 		{
1304 			VK_SHADER_STAGE_VERTEX_BIT,
1305 			VK_SHADER_STAGE_FRAGMENT_BIT,
1306 		};
1307 		const VkShaderStageFlagBits testParamShaders1[] =
1308 		{
1309 			VK_SHADER_STAGE_VERTEX_BIT,
1310 			VK_SHADER_STAGE_GEOMETRY_BIT,
1311 			VK_SHADER_STAGE_FRAGMENT_BIT,
1312 		};
1313 		const VkShaderStageFlagBits testParamShaders2[] =
1314 		{
1315 			VK_SHADER_STAGE_VERTEX_BIT,
1316 			VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
1317 			VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT,
1318 			VK_SHADER_STAGE_FRAGMENT_BIT,
1319 		};
1320 		const CacheTestParam testParams[] =
1321 		{
1322 			CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_FALSE, DE_FALSE),
1323 			CacheTestParam(testParamShaders1, DE_LENGTH_OF_ARRAY(testParamShaders1), DE_FALSE, DE_FALSE),
1324 			CacheTestParam(testParamShaders2, DE_LENGTH_OF_ARRAY(testParamShaders2), DE_FALSE, DE_FALSE),
1325 			CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_TRUE, DE_FALSE),
1326 			CacheTestParam(testParamShaders1, DE_LENGTH_OF_ARRAY(testParamShaders1), DE_TRUE, DE_FALSE),
1327 			CacheTestParam(testParamShaders2, DE_LENGTH_OF_ARRAY(testParamShaders2), DE_TRUE, DE_FALSE),
1328 			CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_FALSE, DE_TRUE),
1329 			CacheTestParam(testParamShaders1, DE_LENGTH_OF_ARRAY(testParamShaders1), DE_FALSE, DE_TRUE),
1330 			CacheTestParam(testParamShaders2, DE_LENGTH_OF_ARRAY(testParamShaders2), DE_FALSE, DE_TRUE),
1331 		};
1332 
1333 		for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1334 			graphicsTests->addChild(newTestCase<GraphicsCacheTest>(testCtx, &testParams[i]));
1335 
1336 		cacheTests->addChild(graphicsTests.release());
1337 	}
1338 
1339 	// Compute Pipeline Tests
1340 	{
1341 		de::MovePtr<tcu::TestCaseGroup> computeTests (new tcu::TestCaseGroup(testCtx, "compute_tests", "Test pipeline creation feedback with compute pipeline."));
1342 
1343 		const VkShaderStageFlagBits testParamShaders0[] =
1344 		{
1345 			VK_SHADER_STAGE_COMPUTE_BIT,
1346 		};
1347 		const CacheTestParam testParams[] =
1348 		{
1349 			CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_FALSE, DE_FALSE),
1350 			CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_TRUE, DE_FALSE),
1351 			CacheTestParam(testParamShaders0, DE_LENGTH_OF_ARRAY(testParamShaders0), DE_FALSE, DE_TRUE),
1352 		};
1353 
1354 		for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1355 			computeTests->addChild(newTestCase<ComputeCacheTest>(testCtx, &testParams[i]));
1356 
1357 		cacheTests->addChild(computeTests.release());
1358 	}
1359 
1360 	return cacheTests.release();
1361 }
1362 
1363 } // pipeline
1364 
1365 } // vkt
1366