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