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