• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 The Khronos Group Inc.
6  * Copyright (c) 2019 Intel Corporation.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief VK_KHR_pipeline_executable_properties
23  *
24  * These tests creates compute and graphics pipelines with a variety of
25  * stages both with and without a pipeline cache and exercise the new
26  * queries provided by VK_KHR_pipeline_executable_properties.
27  *
28  * For each query type, it asserts that the query works and doesn't crash
29  * and returns consistent results:
30  *
31  *  - The tests assert that the same set of pipeline executables is
32  *    reported regardless of whether or not a pipeline cache is used.
33  *
34  *  - For each pipeline executable, the tests assert that the same set of
35  *    statistics is returned regardless of whether or not a pipeline cache
36  *    is used.
37  *
38  *  - For each pipeline executable, the tests assert that the same set of
39  *    statistics is returned regardless of whether or not
40  *    CAPTURE_INTERNAL_REPRESENTATIONS_BIT is set.
41  *
42  *  - For each pipeline executable, the tests assert that the same set of
43  *    internal representations is returned regardless of whether or not a
44  *    pipeline cache is used.
45  *
46  *  - For each string returned (statistic names, etc.) the tests assert
47  *    that the string is NULL terminated.
48  *
49  *  - For each statistic, the tests compare the results of the two
50  *    compilations and report any differences.  (Statistics differing
51  *    between two compilations is not considered a failure.)
52  *
53  *  - For each binary internal representation, the tests attempt to assert
54  *    that the amount of data returned by the implementation matches the
55  *    amount the implementation claims.  (It's impossible to exactly do
56  *    this but the tests give it a good try.)
57  *
58  * All of the returned data is recorded in the output file.
59  *
60  *//*--------------------------------------------------------------------*/
61 
62 #include "vktPipelineExecutablePropertiesTests.hpp"
63 #include "vktPipelineVertexUtil.hpp"
64 #include "vktTestCase.hpp"
65 #include "vktTestCaseUtil.hpp"
66 #include "vkMemUtil.hpp"
67 #include "vkBuilderUtil.hpp"
68 #include "vkRefUtil.hpp"
69 #include "vkTypeUtil.hpp"
70 #include "vkObjUtil.hpp"
71 #include "tcuTestLog.hpp"
72 
73 #include <sstream>
74 #include <vector>
75 
76 namespace vkt
77 {
78 namespace pipeline
79 {
80 
81 using namespace vk;
82 
83 namespace
84 {
85 enum
86 {
87 	VK_MAX_SHADER_STAGES = 6,
88 };
89 
90 enum
91 {
92 	PIPELINE_CACHE_NDX_INITIAL = 0,
93 	PIPELINE_CACHE_NDX_CACHED = 1,
94 	PIPELINE_CACHE_NDX_COUNT,
95 };
96 
97 // helper functions
98 
getShaderFlagStr(const VkShaderStageFlags shader,bool isDescription)99 std::string getShaderFlagStr(const VkShaderStageFlags	shader,
100 							 bool						isDescription)
101 {
102 	std::ostringstream desc;
103 	if (shader & VK_SHADER_STAGE_COMPUTE_BIT)
104 	{
105 		desc << ((isDescription) ? "compute stage" : "compute_stage");
106 	}
107 	else
108 	{
109 		desc << ((isDescription) ? "vertex stage" : "vertex_stage");
110 		if (shader & VK_SHADER_STAGE_GEOMETRY_BIT)
111 			desc << ((isDescription) ? " geometry stage" : "_geometry_stage");
112 		if (shader & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
113 			desc << ((isDescription) ? " tessellation control stage" : "_tessellation_control_stage");
114 		if (shader & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
115 			desc << ((isDescription) ? " tessellation evaluation stage" : "_tessellation_evaluation_stage");
116 		desc << ((isDescription) ? " fragment stage" : "_fragment_stage");
117 	}
118 
119 	return desc.str();
120 }
121 
getShaderFlagsStr(const VkShaderStageFlags flags)122 std::string getShaderFlagsStr (const VkShaderStageFlags flags)
123 {
124 	std::ostringstream stream;
125 	bool empty = true;
126 	for (deUint32 b = 0; b < 8 * sizeof(flags); b++)
127 	{
128 		if (flags & (1u << b))
129 		{
130 			if (empty)
131 			{
132 				empty = false;
133 			}
134 			else
135 			{
136 				stream << ", ";
137 			}
138 
139 			stream << getShaderFlagStr((VkShaderStageFlagBits)(1u << b), true);
140 		}
141 	}
142 
143 	if (empty)
144 	{
145 		stream << "none";
146 	}
147 
148 	return stream.str();
149 }
150 
151 // helper classes
152 class ExecutablePropertiesTestParam
153 {
154 public:
155 								ExecutablePropertiesTestParam	(PipelineConstructionType		pipelineConstructionType,
156 																 const VkShaderStageFlags		shaders,
157 																 deBool							testStatistics,
158 																 deBool							testInternalRepresentations);
159 	virtual						~ExecutablePropertiesTestParam	(void)	= default;
160 	virtual const std::string	generateTestName				(void)	const;
161 	virtual const std::string	generateTestDescription			(void)	const;
getPipelineConstructionType(void) const162 	PipelineConstructionType	getPipelineConstructionType		(void)	const	{ return m_pipelineConstructionType; }
getShaderFlags(void) const163 	VkShaderStageFlags			getShaderFlags					(void)	const	{ return m_shaders; }
getTestStatistics(void) const164 	deBool						getTestStatistics				(void)	const	{ return m_testStatistics; }
getTestInternalRepresentations(void) const165 	deBool						getTestInternalRepresentations	(void)	const	{ return m_testInternalRepresentations; }
166 
167 protected:
168 	PipelineConstructionType	m_pipelineConstructionType;
169 	VkShaderStageFlags			m_shaders;
170 	bool						m_testStatistics;
171 	bool						m_testInternalRepresentations;
172 };
173 
ExecutablePropertiesTestParam(PipelineConstructionType pipelineConstructionType,const VkShaderStageFlags shaders,deBool testStatistics,deBool testInternalRepresentations)174 ExecutablePropertiesTestParam::ExecutablePropertiesTestParam (PipelineConstructionType pipelineConstructionType, const VkShaderStageFlags shaders, deBool testStatistics, deBool testInternalRepresentations)
175 	: m_pipelineConstructionType	(pipelineConstructionType)
176 	, m_shaders						(shaders)
177 	, m_testStatistics				(testStatistics)
178 	, m_testInternalRepresentations	(testInternalRepresentations)
179 {
180 }
181 
generateTestName(void) const182 const std::string ExecutablePropertiesTestParam::generateTestName (void) const
183 {
184 	std::string result(getShaderFlagStr(m_shaders, false));
185 
186 	if (m_testStatistics)
187 		result += "_statistics";
188 	if (m_testInternalRepresentations)
189 		result += "_internal_representations";
190 
191 	return result;
192 }
193 
generateTestDescription(void) const194 const std::string ExecutablePropertiesTestParam::generateTestDescription (void) const
195 {
196 	std::string result;
197 	if (m_testStatistics)
198 	{
199 		result += "Get pipeline executable statistics";
200 		if (m_testInternalRepresentations)
201 		{
202 			result += " and internal representations";
203 		}
204 	}
205 	else if (m_testInternalRepresentations)
206 	{
207 		result += "Get pipeline executable internal representations";
208 	}
209 	else
210 	{
211 		result += "Get pipeline executable properties";
212 	}
213 
214 	result += " with " + getShaderFlagStr(m_shaders, true);
215 
216 	return result;
217 }
218 
219 template <class Test>
newTestCase(tcu::TestContext & testContext,const ExecutablePropertiesTestParam * testParam)220 vkt::TestCase* newTestCase (tcu::TestContext&		testContext,
221 							const ExecutablePropertiesTestParam*	testParam)
222 {
223 	return new Test(testContext,
224 					testParam->generateTestName().c_str(),
225 					testParam->generateTestDescription().c_str(),
226 					testParam);
227 }
228 
229 // Test Classes
230 class ExecutablePropertiesTest : public vkt::TestCase
231 {
232 public:
ExecutablePropertiesTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const ExecutablePropertiesTestParam * param)233 							ExecutablePropertiesTest(tcu::TestContext&		testContext,
234 										   const std::string&		name,
235 										   const std::string&		description,
236 										   const ExecutablePropertiesTestParam*	param)
237 								: vkt::TestCase (testContext, name, description)
238 								, m_param (*param)
239 								{ }
~ExecutablePropertiesTest(void)240 	virtual					~ExecutablePropertiesTest (void) { }
241 protected:
242 	const ExecutablePropertiesTestParam	m_param;
243 };
244 
245 class ExecutablePropertiesTestInstance : public vkt::TestInstance
246 {
247 public:
248 							ExecutablePropertiesTestInstance			(Context&				context,
249 															 const ExecutablePropertiesTestParam*	param);
250 	virtual					~ExecutablePropertiesTestInstance			(void);
251 	virtual tcu::TestStatus iterate							(void);
252 protected:
253 	virtual tcu::TestStatus verifyStatistics				(deUint32 binaryNdx);
254 	virtual tcu::TestStatus verifyInternalRepresentations	(deUint32 binaryNdx);
255 	virtual tcu::TestStatus verifyTestResult				(void);
256 protected:
257 	const ExecutablePropertiesTestParam*	m_param;
258 
259 	Move<VkPipelineCache>	m_cache;
260 	deBool					m_extensions;
261 
262 	Move<VkPipeline>		m_pipeline[PIPELINE_CACHE_NDX_COUNT];
263 
getPipeline(deUint32 ndx)264 	virtual VkPipeline		getPipeline(deUint32 ndx) { return m_pipeline[ndx].get(); }
265 };
266 
ExecutablePropertiesTestInstance(Context & context,const ExecutablePropertiesTestParam * param)267 ExecutablePropertiesTestInstance::ExecutablePropertiesTestInstance (Context&					context,
268 												const ExecutablePropertiesTestParam*	param)
269 	: TestInstance		(context)
270 	, m_param			(param)
271 	, m_extensions		(m_context.requireDeviceFunctionality("VK_KHR_pipeline_executable_properties"))
272 {
273 	const DeviceInterface&	vk				= m_context.getDeviceInterface();
274 	const VkDevice			vkDevice		= m_context.getDevice();
275 
276 	const VkPipelineCacheCreateInfo pipelineCacheCreateInfo =
277 	{
278 		VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,			// VkStructureType				sType;
279 		DE_NULL,												// const void*					pNext;
280 		0u,														// VkPipelineCacheCreateFlags	flags;
281 		0u,														// deUintptr					initialDataSize;
282 		DE_NULL,												// const void*					pInitialData;
283 	};
284 
285 	m_cache = createPipelineCache(vk, vkDevice, &pipelineCacheCreateInfo);
286 }
287 
~ExecutablePropertiesTestInstance(void)288 ExecutablePropertiesTestInstance::~ExecutablePropertiesTestInstance (void)
289 {
290 }
291 
iterate(void)292 tcu::TestStatus ExecutablePropertiesTestInstance::iterate (void)
293 {
294 	return verifyTestResult();
295 }
296 
297 bool
checkString(const char * string,size_t size)298 checkString(const char *string, size_t size)
299 {
300 	size_t i = 0;
301 	for (; i < size; i++)
302 	{
303 		if (string[i] == 0)
304 		{
305 			break;
306 		}
307 	}
308 
309 	// The string needs to be non-empty and null terminated
310 	if (i == 0 || i >= size)
311 	{
312 		return false;
313 	}
314 
315 	return true;
316 }
317 
verifyStatistics(deUint32 executableNdx)318 tcu::TestStatus ExecutablePropertiesTestInstance::verifyStatistics (deUint32 executableNdx)
319 {
320 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
321 	const VkDevice				vkDevice	= m_context.getDevice();
322 	tcu::TestLog				&log		= m_context.getTestContext().getLog();
323 
324 	std::vector<VkPipelineExecutableStatisticKHR> statistics[PIPELINE_CACHE_NDX_COUNT];
325 
326 	for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
327 	{
328 		const VkPipelineExecutableInfoKHR pipelineExecutableInfo =
329 		{
330 			VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR,	// VkStructureType					sType;
331 			DE_NULL,										// const void*						pNext;
332 			getPipeline(ndx),								// VkPipeline						pipeline;
333 			executableNdx,									// uint32_t							executableIndex;
334 		};
335 
336 		deUint32 statisticCount = 0;
337 		VK_CHECK(vk.getPipelineExecutableStatisticsKHR(vkDevice, &pipelineExecutableInfo, &statisticCount, DE_NULL));
338 
339 		if (statisticCount == 0)
340 		{
341 			continue;
342 		}
343 
344 		statistics[ndx].resize(statisticCount);
345 		for (deUint32 statNdx = 0; statNdx < statisticCount; statNdx++)
346 		{
347 			deMemset(&statistics[ndx][statNdx], 0, sizeof(statistics[ndx][statNdx]));
348 			statistics[ndx][statNdx].sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_STATISTIC_KHR;
349 			statistics[ndx][statNdx].pNext = DE_NULL;
350 		}
351 		VK_CHECK(vk.getPipelineExecutableStatisticsKHR(vkDevice, &pipelineExecutableInfo, &statisticCount, &statistics[ndx][0]));
352 
353 		for (deUint32 statNdx = 0; statNdx < statisticCount; statNdx++)
354 		{
355 			if (!checkString(statistics[ndx][statNdx].name, DE_LENGTH_OF_ARRAY(statistics[ndx][statNdx].name)))
356 			{
357 				return tcu::TestStatus::fail("Invalid statistic name string");
358 			}
359 
360 			for (deUint32 otherNdx = 0; otherNdx < statNdx; otherNdx++)
361 			{
362 				if (deMemCmp(statistics[ndx][statNdx].name, statistics[ndx][otherNdx].name,
363 							 DE_LENGTH_OF_ARRAY(statistics[ndx][statNdx].name)) == 0)
364 				{
365 					return tcu::TestStatus::fail("Statistic name string not unique within the executable");
366 				}
367 			}
368 
369 			if (!checkString(statistics[ndx][statNdx].description, DE_LENGTH_OF_ARRAY(statistics[ndx][statNdx].description)))
370 			{
371 				return tcu::TestStatus::fail("Invalid statistic description string");
372 			}
373 
374 			if (statistics[ndx][statNdx].format == VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR)
375 			{
376 				if (statistics[ndx][statNdx].value.b32 != VK_TRUE && statistics[ndx][statNdx].value.b32 != VK_FALSE)
377 				{
378 					return tcu::TestStatus::fail("Boolean statistic is neither VK_TRUE nor VK_FALSE");
379 				}
380 			}
381 		}
382 	}
383 
384 	if (statistics[0].size() != statistics[1].size())
385 	{
386 		return tcu::TestStatus::fail("Identical pipelines have different numbers of statistics");
387 	}
388 
389 	if (statistics[0].size() == 0)
390 	{
391 		return tcu::TestStatus::pass("No statistics reported");
392 	}
393 
394 	// Both compiles had better have specified the same infos
395 	for (deUint32 statNdx0 = 0; statNdx0 < statistics[0].size(); statNdx0++)
396 	{
397 		deUint32 statNdx1 = 0;
398 		for (; statNdx1 < statistics[1].size(); statNdx1++)
399 		{
400 			if (deMemCmp(statistics[0][statNdx0].name, statistics[1][statNdx1].name,
401 						 DE_LENGTH_OF_ARRAY(statistics[0][statNdx0].name)) == 0)
402 			{
403 				break;
404 			}
405 		}
406 		if (statNdx1 >= statistics[1].size())
407 		{
408 			return tcu::TestStatus::fail("Identical pipelines have different statistics");
409 		}
410 
411 		if (deMemCmp(statistics[0][statNdx0].description, statistics[1][statNdx1].description,
412 					 DE_LENGTH_OF_ARRAY(statistics[0][statNdx0].description)) != 0)
413 		{
414 			return tcu::TestStatus::fail("Invalid binary description string");
415 		}
416 
417 		if (statistics[0][statNdx0].format != statistics[1][statNdx1].format)
418 		{
419 			return tcu::TestStatus::fail("Identical pipelines have statistics with different formats");
420 		}
421 
422 		switch (statistics[0][statNdx0].format)
423 		{
424 			case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_BOOL32_KHR:
425 			{
426 				bool match = statistics[0][statNdx0].value.b32 == statistics[1][statNdx1].value.b32;
427 				log << tcu::TestLog::Message
428 					<< statistics[0][statNdx0].name << ": "
429 					<< (statistics[0][statNdx0].value.b32 ? "VK_TRUE" : "VK_FALSE")
430 					<< (match ? "" : " (non-deterministic)")
431 					<< " (" << statistics[0][statNdx0].description << ")"
432 					<< tcu::TestLog::EndMessage;
433 				break;
434 			}
435 			case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_INT64_KHR:
436 			{
437 				bool match = statistics[0][statNdx0].value.i64 == statistics[1][statNdx1].value.i64;
438 				log << tcu::TestLog::Message
439 					<< statistics[0][statNdx0].name << ": "
440 					<< statistics[0][statNdx0].value.i64
441 					<< (match ? "" : " (non-deterministic)")
442 					<< " (" << statistics[0][statNdx0].description << ")"
443 					<< tcu::TestLog::EndMessage;
444 				break;
445 			}
446 			case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR:
447 			{
448 				bool match = statistics[0][statNdx0].value.u64 == statistics[1][statNdx1].value.u64;
449 				log << tcu::TestLog::Message
450 					<< statistics[0][statNdx0].name << ": "
451 					<< statistics[0][statNdx0].value.u64
452 					<< (match ? "" : " (non-deterministic)")
453 					<< " (" << statistics[0][statNdx0].description << ")"
454 					<< tcu::TestLog::EndMessage;
455 				break;
456 			}
457 			case VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_FLOAT64_KHR:
458 			{
459 				bool match = statistics[0][statNdx0].value.f64 == statistics[1][statNdx1].value.f64;
460 				log << tcu::TestLog::Message
461 					<< statistics[0][statNdx0].name << ": "
462 					<< statistics[0][statNdx0].value.f64
463 					<< (match ? "" : " (non-deterministic)")
464 					<< " (" << statistics[0][statNdx0].description << ")"
465 					<< tcu::TestLog::EndMessage;
466 				break;
467 			}
468 			default:
469 				return tcu::TestStatus::fail("Invalid statistic format");
470 		}
471 	}
472 
473 	return tcu::TestStatus::pass("Pass");
474 }
475 
verifyInternalRepresentations(deUint32 executableNdx)476 tcu::TestStatus ExecutablePropertiesTestInstance::verifyInternalRepresentations (deUint32 executableNdx)
477 {
478 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
479 	const VkDevice				vkDevice	= m_context.getDevice();
480 	tcu::TestLog				&log		= m_context.getTestContext().getLog();
481 
482 	// We only care about internal representations on the second pipeline.
483 	// We still compile twice to ensure that we still get the right thing
484 	// even if the pipeline is hot in the cache.
485 	const VkPipelineExecutableInfoKHR pipelineExecutableInfo =
486 	{
487 		VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INFO_KHR,	// VkStructureType					sType;
488 		DE_NULL,										// const void*						pNext;
489 		getPipeline(1),									// VkPipeline						pipeline;
490 		executableNdx,									// uint32_t							executableIndex;
491 	};
492 
493 	std::vector<VkPipelineExecutableInternalRepresentationKHR> irs;
494 	std::vector<std::vector<deUint8>> irDatas;
495 
496 	deUint32 irCount = 0;
497 	VK_CHECK(vk.getPipelineExecutableInternalRepresentationsKHR(vkDevice, &pipelineExecutableInfo, &irCount, DE_NULL));
498 
499 	if (irCount == 0)
500 	{
501 		return tcu::TestStatus::pass("No internal representations reported");
502 	}
503 
504 	irs.resize(irCount);
505 	irDatas.resize(irCount);
506 	for (deUint32 irNdx = 0; irNdx < irCount; irNdx++)
507 	{
508 		deMemset(&irs[irNdx], 0, sizeof(irs[irNdx]));
509 		irs[irNdx].sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_INTERNAL_REPRESENTATION_KHR;
510 		irs[irNdx].pNext = DE_NULL;
511 	}
512 	VK_CHECK(vk.getPipelineExecutableInternalRepresentationsKHR(vkDevice, &pipelineExecutableInfo, &irCount, &irs[0]));
513 
514 	for (deUint32 irNdx = 0; irNdx < irCount; irNdx++)
515 	{
516 		if (!checkString(irs[irNdx].name, DE_LENGTH_OF_ARRAY(irs[irNdx].name)))
517 		{
518 			return tcu::TestStatus::fail("Invalid internal representation name string");
519 		}
520 
521 		for (deUint32 otherNdx = 0; otherNdx < irNdx; otherNdx++)
522 		{
523 			if (deMemCmp(irs[irNdx].name, irs[otherNdx].name,
524 						 DE_LENGTH_OF_ARRAY(irs[irNdx].name)) == 0)
525 			{
526 				return tcu::TestStatus::fail("Internal representation name string not unique within the executable");
527 			}
528 		}
529 
530 		if (!checkString(irs[irNdx].description, DE_LENGTH_OF_ARRAY(irs[irNdx].description)))
531 		{
532 			return tcu::TestStatus::fail("Invalid binary description string");
533 		}
534 
535 		if (irs[irNdx].dataSize == 0)
536 		{
537 			return tcu::TestStatus::fail("Internal representation has no data");
538 		}
539 
540 		irDatas[irNdx].resize(irs[irNdx].dataSize);
541 		irs[irNdx].pData = &irDatas[irNdx][0];
542 		if (irs[irNdx].isText)
543 		{
544 			// For binary data the size is important.  We check that the
545 			// implementation fills the whole buffer by filling it with
546 			// garbage first and then looking for that same garbage later.
547 			for (size_t i = 0; i < irs[irNdx].dataSize; i++)
548 			{
549 				irDatas[irNdx][i] = (deUint8)(37 * (17 + i));
550 			}
551 		}
552 	}
553 
554 	VK_CHECK(vk.getPipelineExecutableInternalRepresentationsKHR(vkDevice, &pipelineExecutableInfo, &irCount, &irs[0]));
555 
556 	for (deUint32 irNdx = 0; irNdx < irCount; irNdx++)
557 	{
558 		if (irs[irNdx].isText)
559 		{
560 			if (!checkString((char *)irs[irNdx].pData, irs[irNdx].dataSize))
561 			{
562 				return tcu::TestStatus::fail("Textual internal representation isn't a valid string");
563 			}
564 			log << tcu::TestLog::Section(irs[irNdx].name, irs[irNdx].description)
565 				<< tcu::LogKernelSource((char *)irs[irNdx].pData)
566 				<< tcu::TestLog::EndSection;
567 		}
568 		else
569 		{
570 			size_t maxMatchingChunkSize = 0;
571 			size_t matchingChunkSize = 0;
572 			for (size_t i = 0; i < irs[irNdx].dataSize; i++)
573 			{
574 				if (irDatas[irNdx][i] == (deUint8)(37 * (17 + i)))
575 				{
576 					matchingChunkSize++;
577 					if (matchingChunkSize > maxMatchingChunkSize)
578 					{
579 						maxMatchingChunkSize = matchingChunkSize;
580 					}
581 				}
582 				else
583 				{
584 					matchingChunkSize = 0;
585 				}
586 			}
587 
588 			// 64 bytes of our random data still being in the buffer probably
589 			// isn't a coincidence
590 			if (matchingChunkSize == irs[irNdx].dataSize || matchingChunkSize >= 64)
591 			{
592 				return tcu::TestStatus::fail("Implementation didn't fill the whole internal representation data buffer");
593 			}
594 
595 			log << tcu::TestLog::Section(irs[irNdx].name, irs[irNdx].description)
596 				<< tcu::TestLog::Message << "Received " << irs[irNdx].dataSize << "B of binary data" << tcu::TestLog::EndMessage
597 				<< tcu::TestLog::EndSection;
598 		}
599 	}
600 
601 	return tcu::TestStatus::pass("Pass");
602 }
603 
verifyTestResult(void)604 tcu::TestStatus ExecutablePropertiesTestInstance::verifyTestResult (void)
605 {
606 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
607 	const VkDevice				vkDevice	= m_context.getDevice();
608 	tcu::TestLog				&log		= m_context.getTestContext().getLog();
609 
610 	std::vector<VkPipelineExecutablePropertiesKHR> props[PIPELINE_CACHE_NDX_COUNT];
611 
612 	for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
613 	{
614 		const VkPipelineInfoKHR pipelineInfo =
615 		{
616 			VK_STRUCTURE_TYPE_PIPELINE_INFO_KHR,	// VkStructureType					sType;
617 			DE_NULL,								// const void*						pNext;
618 			getPipeline(ndx),						// VkPipeline						pipeline;
619 
620 		};
621 		deUint32 executableCount = 0;
622 		VK_CHECK(vk.getPipelineExecutablePropertiesKHR(vkDevice, &pipelineInfo, &executableCount, DE_NULL));
623 
624 		if (executableCount == 0)
625 		{
626 			continue;
627 		}
628 
629 		props[ndx].resize(executableCount);
630 		for (deUint32 execNdx = 0; execNdx < executableCount; execNdx++)
631 		{
632 			deMemset(&props[ndx][execNdx], 0, sizeof(props[ndx][execNdx]));
633 			props[ndx][execNdx].sType = VK_STRUCTURE_TYPE_PIPELINE_EXECUTABLE_PROPERTIES_KHR;
634 			props[ndx][execNdx].pNext = DE_NULL;
635 		}
636 		VK_CHECK(vk.getPipelineExecutablePropertiesKHR(vkDevice, &pipelineInfo, &executableCount, &props[ndx][0]));
637 
638 		for (deUint32 execNdx = 0; execNdx < executableCount; execNdx++)
639 		{
640 			if (!checkString(props[ndx][execNdx].name, DE_LENGTH_OF_ARRAY(props[ndx][execNdx].name)))
641 			{
642 				return tcu::TestStatus::fail("Invalid binary name string");
643 			}
644 
645 			for (deUint32 otherNdx = 0; otherNdx < execNdx; otherNdx++)
646 			{
647 				if (deMemCmp(props[ndx][execNdx].name, props[ndx][otherNdx].name,
648 							 DE_LENGTH_OF_ARRAY(props[ndx][execNdx].name)) == 0)
649 				{
650 					return tcu::TestStatus::fail("Binary name string not unique within the pipeline");
651 				}
652 			}
653 
654 			if (!checkString(props[ndx][execNdx].description, DE_LENGTH_OF_ARRAY(props[ndx][execNdx].description)))
655 			{
656 				return tcu::TestStatus::fail("Invalid binary description string");
657 			}
658 
659 			// Check that the binary only contains stages actually used to
660 			// compile the pipeline
661 			VkShaderStageFlags stages = props[ndx][execNdx].stages;
662 			stages &= ~m_param->getShaderFlags();
663 			if (stages != 0)
664 			{
665 				return tcu::TestStatus::fail("Binary uses unprovided stage");
666 			}
667 		}
668 	}
669 
670 	if (props[0].size() != props[1].size())
671 	{
672 		return tcu::TestStatus::fail("Identical pipelines have different numbers of props");
673 	}
674 
675 	if (props[0].size() == 0)
676 	{
677 		return tcu::TestStatus::pass("No executables reported");
678 	}
679 
680 	// Both compiles had better have specified the same infos
681 	for (deUint32 execNdx0 = 0; execNdx0 < props[0].size(); execNdx0++)
682 	{
683 		deUint32 execNdx1 = 0;
684 		for (; execNdx1 < props[1].size(); execNdx1++)
685 		{
686 			if (deMemCmp(props[0][execNdx0].name, props[1][execNdx1].name,
687 						 DE_LENGTH_OF_ARRAY(props[0][execNdx0].name)) == 0)
688 			{
689 				break;
690 			}
691 		}
692 		if (execNdx1 >= props[1].size())
693 		{
694 			return tcu::TestStatus::fail("Identical pipelines have different sets of executables");
695 		}
696 
697 		if (deMemCmp(props[0][execNdx0].description, props[1][execNdx1].description,
698 					 DE_LENGTH_OF_ARRAY(props[0][execNdx0].description)) != 0)
699 		{
700 			return tcu::TestStatus::fail("Same binary has different descriptions");
701 		}
702 
703 		if (props[0][execNdx0].stages != props[1][execNdx1].stages)
704 		{
705 			return tcu::TestStatus::fail("Same binary has different stages");
706 		}
707 
708 		if (props[0][execNdx0].subgroupSize != props[1][execNdx1].subgroupSize)
709 		{
710 			return tcu::TestStatus::fail("Same binary has different subgroup sizes");
711 		}
712 	}
713 
714 	log << tcu::TestLog::Section("Binaries", "Binaries reported for this pipeline");
715 	log << tcu::TestLog::Message << "Pipeline reported " << props[0].size() << " props" << tcu::TestLog::EndMessage;
716 
717 	tcu::TestStatus status = tcu::TestStatus::pass("Pass");
718 	for (deUint32 execNdx = 0; execNdx < props[0].size(); execNdx++)
719 	{
720 		log << tcu::TestLog::Section(props[0][execNdx].name, props[0][execNdx].description);
721 		log << tcu::TestLog::Message << "Name: " << props[0][execNdx].name << tcu::TestLog::EndMessage;
722 		log << tcu::TestLog::Message << "Description: " << props[0][execNdx].description << tcu::TestLog::EndMessage;
723 		log << tcu::TestLog::Message << "Stages: " << getShaderFlagsStr(props[0][execNdx].stages) << tcu::TestLog::EndMessage;
724 		log << tcu::TestLog::Message << "Subgroup Size: " << props[0][execNdx].subgroupSize << tcu::TestLog::EndMessage;
725 
726 		if (m_param->getTestStatistics())
727 		{
728 			status = verifyStatistics(execNdx);
729 			if (status.getCode() != QP_TEST_RESULT_PASS)
730 			{
731 				log << tcu::TestLog::EndSection;
732 				break;
733 			}
734 		}
735 
736 		if (m_param->getTestInternalRepresentations())
737 		{
738 			status = verifyInternalRepresentations(execNdx);
739 			if (status.getCode() != QP_TEST_RESULT_PASS)
740 			{
741 				log << tcu::TestLog::EndSection;
742 				break;
743 			}
744 		}
745 
746 		log << tcu::TestLog::EndSection;
747 	}
748 
749 	log << tcu::TestLog::EndSection;
750 
751 	return status;
752 }
753 
754 class GraphicsExecutablePropertiesTest : public ExecutablePropertiesTest
755 {
756 public:
GraphicsExecutablePropertiesTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const ExecutablePropertiesTestParam * param)757 							GraphicsExecutablePropertiesTest	(tcu::TestContext&		testContext,
758 													 const std::string&	name,
759 													 const std::string&	description,
760 													 const ExecutablePropertiesTestParam*	param)
761 								: ExecutablePropertiesTest (testContext, name, description, param)
762 								{ }
~GraphicsExecutablePropertiesTest(void)763 	virtual					~GraphicsExecutablePropertiesTest	(void) { }
764 	virtual void			initPrograms		(SourceCollections&	programCollection) const;
765 	virtual TestInstance*	createInstance		(Context&				context) const;
766 	void					checkSupport		(Context& context) const;
767 };
768 
769 class GraphicsExecutablePropertiesTestInstance : public ExecutablePropertiesTestInstance
770 {
771 public:
772 							GraphicsExecutablePropertiesTestInstance	(Context&								context,
773 																		 const ExecutablePropertiesTestParam*	param);
774 	virtual					~GraphicsExecutablePropertiesTestInstance	(void);
775 
776 protected:
777 	void					preparePipelineWrapper						(GraphicsPipelineWrapper&	gpw,
778 																		 VkShaderModule				vertShaderModule,
779 																		 VkShaderModule				tescShaderModule,
780 																		 VkShaderModule				teseShaderModule,
781 																		 VkShaderModule				geomShaderModule,
782 																	 VkShaderModule				fragShaderModule);
783 
getPipeline(deUint32 ndx)784 	VkPipeline				getPipeline									(deUint32 ndx) override
785 	{
786 		return m_pipelineWrapper[ndx].getPipeline();
787 	};
788 
789 protected:
790 	const tcu::UVec2					m_renderSize;
791 	const VkFormat						m_colorFormat;
792 	const VkFormat						m_depthFormat;
793 	Move<VkPipelineLayout>				m_pipelineLayout;
794 	GraphicsPipelineWrapper				m_pipelineWrapper[PIPELINE_CACHE_NDX_COUNT];
795 	Move<VkRenderPass>					m_renderPass;
796 };
797 
initPrograms(SourceCollections & programCollection) const798 void GraphicsExecutablePropertiesTest::initPrograms (SourceCollections& programCollection) const
799 {
800 	programCollection.glslSources.add("color_vert") << glu::VertexSource(
801 				"#version 310 es\n"
802 				"layout(location = 0) in vec4 position;\n"
803 				"layout(location = 1) in vec4 color;\n"
804 				"layout(location = 0) out highp vec4 vtxColor;\n"
805 				"void main (void)\n"
806 				"{\n"
807 				"  gl_Position = position;\n"
808 				"  vtxColor = color;\n"
809 				"}\n");
810 
811 	programCollection.glslSources.add("color_frag") << glu::FragmentSource(
812 				"#version 310 es\n"
813 				"layout(location = 0) in highp vec4 vtxColor;\n"
814 				"layout(location = 0) out highp vec4 fragColor;\n"
815 				"void main (void)\n"
816 				"{\n"
817 				"  fragColor = vtxColor;\n"
818 				"}\n");
819 
820 	if (m_param.getShaderFlags() & VK_SHADER_STAGE_GEOMETRY_BIT)
821 	{
822 		programCollection.glslSources.add("dummy_geo") << glu::GeometrySource(
823 					"#version 450 \n"
824 					"layout(triangles) in;\n"
825 					"layout(triangle_strip, max_vertices = 3) out;\n"
826 					"layout(location = 0) in highp vec4 in_vtxColor[];\n"
827 					"layout(location = 0) out highp vec4 vtxColor;\n"
828 					"out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };\n"
829 					"in gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_in[];\n"
830 					"void main (void)\n"
831 					"{\n"
832 					"  for(int ndx=0; ndx<3; ndx++)\n"
833 					"  {\n"
834 					"    gl_Position = gl_in[ndx].gl_Position;\n"
835 					"    gl_PointSize = gl_in[ndx].gl_PointSize;\n"
836 					"    vtxColor    = in_vtxColor[ndx];\n"
837 					"    EmitVertex();\n"
838 					"  }\n"
839 					"  EndPrimitive();\n"
840 						"}\n");
841 	}
842 	if (m_param.getShaderFlags() & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
843 	{
844 		programCollection.glslSources.add("basic_tcs") << glu::TessellationControlSource(
845 					"#version 450 \n"
846 					"layout(vertices = 3) out;\n"
847 					"layout(location = 0) in highp vec4 color[];\n"
848 					"layout(location = 0) out highp vec4 vtxColor[];\n"
849 					"out gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_out[3];\n"
850 					"in gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_in[gl_MaxPatchVertices];\n"
851 					"void main()\n"
852 					"{\n"
853 					"  gl_TessLevelOuter[0] = 4.0;\n"
854 					"  gl_TessLevelOuter[1] = 4.0;\n"
855 					"  gl_TessLevelOuter[2] = 4.0;\n"
856 					"  gl_TessLevelInner[0] = 4.0;\n"
857 					"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
858 					"  gl_out[gl_InvocationID].gl_PointSize = gl_in[gl_InvocationID].gl_PointSize;\n"
859 					"  vtxColor[gl_InvocationID] = color[gl_InvocationID];\n"
860 					"}\n");
861 
862 		programCollection.glslSources.add("basic_tes") << glu::TessellationEvaluationSource(
863 					"#version 450 \n"
864 					"layout(triangles, fractional_even_spacing, ccw) in;\n"
865 					"layout(location = 0) in highp vec4 colors[];\n"
866 					"layout(location = 0) out highp vec4 vtxColor;\n"
867 					"out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };\n"
868 					"in gl_PerVertex { vec4 gl_Position; float gl_PointSize; } gl_in[gl_MaxPatchVertices];\n"
869 					"void main() \n"
870 					"{\n"
871 					"  float u = gl_TessCoord.x;\n"
872 					"  float v = gl_TessCoord.y;\n"
873 					"  float w = gl_TessCoord.z;\n"
874 					"  vec4 pos = vec4(0);\n"
875 					"  vec4 color = vec4(0);\n"
876 					"  pos.xyz += u * gl_in[0].gl_Position.xyz;\n"
877 					"  color.xyz += u * colors[0].xyz;\n"
878 					"  pos.xyz += v * gl_in[1].gl_Position.xyz;\n"
879 					"  color.xyz += v * colors[1].xyz;\n"
880 					"  pos.xyz += w * gl_in[2].gl_Position.xyz;\n"
881 					"  color.xyz += w * colors[2].xyz;\n"
882 					"  pos.w = 1.0;\n"
883 					"  color.w = 1.0;\n"
884 					"  gl_Position = pos;\n"
885 					"  gl_PointSize = gl_in[0].gl_PointSize;"
886 					"  vtxColor = color;\n"
887 					"}\n");
888 	}
889 }
890 
createInstance(Context & context) const891 TestInstance* GraphicsExecutablePropertiesTest::createInstance (Context& context) const
892 {
893 	return new GraphicsExecutablePropertiesTestInstance(context, &m_param);
894 }
895 
checkSupport(Context & context) const896 void GraphicsExecutablePropertiesTest::checkSupport(Context& context) const
897 {
898 	VkShaderStageFlags			shaderFlags	= m_param.getShaderFlags();
899 	VkPhysicalDeviceFeatures	features	= context.getDeviceFeatures();
900 	if ((shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT) && (features.geometryShader == VK_FALSE))
901 		TCU_THROW(NotSupportedError, "Geometry Shader Not Supported");
902 	if ((shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) ||
903 		(shaderFlags & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT))
904 	{
905 		if (features.tessellationShader == VK_FALSE)
906 			TCU_THROW(NotSupportedError, "Tessellation Not Supported");
907 	}
908 
909 	checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_param.getPipelineConstructionType());
910 }
911 
GraphicsExecutablePropertiesTestInstance(Context & context,const ExecutablePropertiesTestParam * param)912 GraphicsExecutablePropertiesTestInstance::GraphicsExecutablePropertiesTestInstance (Context&					context,
913 																const ExecutablePropertiesTestParam*	param)
914 	: ExecutablePropertiesTestInstance		(context, param)
915 	, m_renderSize							(32u, 32u)
916 	, m_colorFormat							(VK_FORMAT_R8G8B8A8_UNORM)
917 	, m_depthFormat							(VK_FORMAT_D16_UNORM)
918 	, m_pipelineWrapper
919 	{
920 		{ m_context.getDeviceInterface(), m_context.getDevice(), param->getPipelineConstructionType(),
921 						(param->getTestStatistics() ? deUint32(VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR) : 0u) },
922 		{ m_context.getDeviceInterface(), m_context.getDevice(), param->getPipelineConstructionType(),
923 						(param->getTestStatistics() ? deUint32(VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR) : 0u) |
924 						// Only check gather internal representations on the second pipeline.
925 						// This way, it's more obvious if they failed to capture due to the pipeline being cached.
926 						(param->getTestInternalRepresentations() ? deUint32(VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR) : 0u) },
927 	}
928 {
929 	const DeviceInterface&	vk				= m_context.getDeviceInterface();
930 	const VkDevice			vkDevice		= m_context.getDevice();
931 
932 	// Create pipeline layout
933 	{
934 		const VkPipelineLayoutCreateInfo pipelineLayoutParams =
935 		{
936 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
937 			DE_NULL,											// const void*						pNext;
938 			0u,													// VkPipelineLayoutCreateFlags		flags;
939 			0u,													// deUint32							setLayoutCount;
940 			DE_NULL,											// const VkDescriptorSetLayout*		pSetLayouts;
941 			0u,													// deUint32							pushConstantRangeCount;
942 			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
943 		};
944 
945 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
946 	}
947 
948 	// Create render pass
949 	m_renderPass = makeRenderPass(vk, vkDevice, m_colorFormat, m_depthFormat);
950 
951 	// Bind shader stages
952 	Move<VkShaderModule> vertShaderModule = createShaderModule(vk, vkDevice, context.getBinaryCollection().get("color_vert"), 0);
953 	Move<VkShaderModule> fragShaderModule = createShaderModule(vk, vkDevice, context.getBinaryCollection().get("color_frag"), 0);
954 	Move<VkShaderModule> tescShaderModule;
955 	Move<VkShaderModule> teseShaderModule;
956 	Move<VkShaderModule> geomShaderModule;
957 
958 	VkShaderStageFlags shaderFlags = m_param->getShaderFlags();
959 	if (shaderFlags & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
960 		tescShaderModule = createShaderModule(vk, vkDevice, context.getBinaryCollection().get("basic_tcs"), 0);
961 	if (shaderFlags & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
962 		teseShaderModule = createShaderModule(vk, vkDevice, context.getBinaryCollection().get("basic_tes"), 0);
963 	if (shaderFlags & VK_SHADER_STAGE_GEOMETRY_BIT)
964 		geomShaderModule = createShaderModule(vk, vkDevice, context.getBinaryCollection().get("dummy_geo"), 0);
965 
966 	for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
967 		preparePipelineWrapper(m_pipelineWrapper[ndx], *vertShaderModule, *tescShaderModule, *teseShaderModule, *geomShaderModule, *fragShaderModule);
968 }
969 
~GraphicsExecutablePropertiesTestInstance(void)970 GraphicsExecutablePropertiesTestInstance::~GraphicsExecutablePropertiesTestInstance (void)
971 {
972 }
973 
preparePipelineWrapper(GraphicsPipelineWrapper & gpw,VkShaderModule vertShaderModule,VkShaderModule tescShaderModule,VkShaderModule teseShaderModule,VkShaderModule geomShaderModule,VkShaderModule fragShaderModule)974 void GraphicsExecutablePropertiesTestInstance::preparePipelineWrapper(GraphicsPipelineWrapper&		gpw,
975 																	  VkShaderModule				vertShaderModule,
976 																	  VkShaderModule				tescShaderModule,
977 																	  VkShaderModule				teseShaderModule,
978 																	  VkShaderModule				geomShaderModule,
979 																	  VkShaderModule				fragShaderModule)
980 {
981 	// Create pipeline
982 	const VkVertexInputBindingDescription vertexInputBindingDescription =
983 	{
984 		0u,									// deUint32				binding;
985 		sizeof(Vertex4RGBA),				// deUint32				strideInBytes;
986 		VK_VERTEX_INPUT_RATE_VERTEX,		// VkVertexInputRate	inputRate;
987 	};
988 
989 	const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
990 	{
991 		{
992 			0u,									// deUint32 location;
993 			0u,									// deUint32 binding;
994 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat format;
995 			0u									// deUint32 offsetInBytes;
996 		},
997 		{
998 			1u,									// deUint32 location;
999 			0u,									// deUint32 binding;
1000 			VK_FORMAT_R32G32B32A32_SFLOAT,		// VkFormat format;
1001 			DE_OFFSET_OF(Vertex4RGBA, color),	// deUint32 offsetInBytes;
1002 		}
1003 	};
1004 
1005 	const VkPipelineVertexInputStateCreateInfo vertexInputStateParams
1006 	{
1007 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType							sType;
1008 		DE_NULL,														// const void*								pNext;
1009 		0u,																// VkPipelineVertexInputStateCreateFlags	flags;
1010 		1u,																// deUint32									vertexBindingDescriptionCount;
1011 		&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
1012 		2u,																// deUint32									vertexAttributeDescriptionCount;
1013 		vertexInputAttributeDescriptions,								// const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
1014 	};
1015 
1016 	const std::vector<VkViewport>	viewport{ makeViewport(m_renderSize) };
1017 	const std::vector<VkRect2D>		scissor{ makeRect2D(m_renderSize) };
1018 
1019 	const VkPipelineColorBlendAttachmentState colorBlendAttachmentState
1020 	{
1021 		VK_FALSE,														// VkBool32		blendEnable;
1022 		VK_BLEND_FACTOR_ONE,											// VkBlendFactor	srcColorBlendFactor;
1023 		VK_BLEND_FACTOR_ZERO,											// VkBlendFactor	dstColorBlendFactor;
1024 		VK_BLEND_OP_ADD,												// VkBlendOp		colorBlendOp;
1025 		VK_BLEND_FACTOR_ONE,											// VkBlendFactor	srcAlphaBlendFactor;
1026 		VK_BLEND_FACTOR_ZERO,											// VkBlendFactor	dstAlphaBlendFactor;
1027 		VK_BLEND_OP_ADD,												// VkBlendOp		alphaBlendOp;
1028 		VK_COLOR_COMPONENT_R_BIT |
1029 		VK_COLOR_COMPONENT_G_BIT |
1030 		VK_COLOR_COMPONENT_B_BIT |
1031 		VK_COLOR_COMPONENT_A_BIT										// VkColorComponentFlags    colorWriteMask;
1032 	};
1033 
1034 	const VkPipelineColorBlendStateCreateInfo colorBlendStateParams
1035 	{
1036 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType;
1037 		DE_NULL,													// const void*									pNext;
1038 		0u,															// VkPipelineColorBlendStateCreateFlags			flags;
1039 		VK_FALSE,													// VkBool32										logicOpEnable;
1040 		VK_LOGIC_OP_COPY,											// VkLogicOp									logicOp;
1041 		1u,															// deUint32										attachmentCount;
1042 		&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments;
1043 		{ 0.0f, 0.0f, 0.0f, 0.0f },									// float										blendConst[4];
1044 	};
1045 
1046 	VkPipelineDepthStencilStateCreateInfo depthStencilStateParams
1047 	{
1048 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType							sType;
1049 		DE_NULL,													// const void*								pNext;
1050 		0u,															// VkPipelineDepthStencilStateCreateFlags	flags;
1051 		VK_TRUE,													// VkBool32									depthTestEnable;
1052 		VK_TRUE,													// VkBool32									depthWriteEnable;
1053 		VK_COMPARE_OP_LESS_OR_EQUAL,								// VkCompareOp								depthCompareOp;
1054 		VK_FALSE,													// VkBool32									depthBoundsTestEnable;
1055 		VK_FALSE,													// VkBool32									stencilTestEnable;
1056 		// VkStencilOpState front;
1057 		{
1058 			VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
1059 			VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
1060 			VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
1061 			VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
1062 			0u,						// deUint32		compareMask;
1063 			0u,						// deUint32		writeMask;
1064 			0u,						// deUint32		reference;
1065 		},
1066 		// VkStencilOpState back;
1067 		{
1068 			VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp;
1069 			VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp;
1070 			VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp;
1071 			VK_COMPARE_OP_NEVER,	// VkCompareOp	compareOp;
1072 			0u,						// deUint32		compareMask;
1073 			0u,						// deUint32		writeMask;
1074 			0u,						// deUint32		reference;
1075 		},
1076 		0.0f,														// float									minDepthBounds;
1077 		1.0f,														// float									maxDepthBounds;
1078 	};
1079 
1080 	gpw.setDefaultTopology((tescShaderModule == DE_NULL) ? VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST : VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
1081 	   .setDefaultRasterizationState()
1082 	   .setDefaultMultisampleState()
1083 	   .setupVertexInputState(&vertexInputStateParams)
1084 	   .setupPreRasterizationShaderState(viewport,
1085 			scissor,
1086 			*m_pipelineLayout,
1087 			*m_renderPass,
1088 			0u,
1089 			vertShaderModule,
1090 			DE_NULL,
1091 			tescShaderModule,
1092 			teseShaderModule,
1093 			geomShaderModule)
1094 	   .setupFragmentShaderState(*m_pipelineLayout, *m_renderPass, 0u, fragShaderModule, &depthStencilStateParams)
1095 	   .setupFragmentOutputState(*m_renderPass, 0u, &colorBlendStateParams)
1096 	   .setMonolithicPipelineLayout(*m_pipelineLayout)
1097 	   .buildPipeline(*m_cache);
1098 }
1099 
1100 class ComputeExecutablePropertiesTest : public ExecutablePropertiesTest
1101 {
1102 public:
ComputeExecutablePropertiesTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const ExecutablePropertiesTestParam * param)1103 							ComputeExecutablePropertiesTest	(tcu::TestContext&		testContext,
1104 													 const std::string&		name,
1105 													 const std::string&		description,
1106 													 const ExecutablePropertiesTestParam*	param)
1107 								: ExecutablePropertiesTest	(testContext, name, description, param)
1108 								{ }
~ComputeExecutablePropertiesTest(void)1109 	virtual					~ComputeExecutablePropertiesTest	(void) { }
1110 	virtual void			initPrograms			(SourceCollections&	programCollection) const;
1111 	virtual TestInstance*	createInstance			(Context&				context) const;
1112 };
1113 
1114 class ComputeExecutablePropertiesTestInstance : public ExecutablePropertiesTestInstance
1115 {
1116 public:
1117 							ComputeExecutablePropertiesTestInstance	(Context&				context,
1118 															 const ExecutablePropertiesTestParam*	param);
1119 	virtual					~ComputeExecutablePropertiesTestInstance	(void);
1120 protected:
1121 	void					buildDescriptorSets				(deUint32 ndx);
1122 	void					buildShader						(deUint32 ndx);
1123 	void					buildPipeline					(deUint32 ndx);
1124 protected:
1125 	Move<VkBuffer>					m_inputBuf;
1126 	de::MovePtr<Allocation>			m_inputBufferAlloc;
1127 	Move<VkShaderModule>			m_computeShaderModule[PIPELINE_CACHE_NDX_COUNT];
1128 
1129 	Move<VkBuffer>					m_outputBuf[PIPELINE_CACHE_NDX_COUNT];
1130 	de::MovePtr<Allocation>			m_outputBufferAlloc[PIPELINE_CACHE_NDX_COUNT];
1131 
1132 	Move<VkDescriptorPool>			m_descriptorPool[PIPELINE_CACHE_NDX_COUNT];
1133 	Move<VkDescriptorSetLayout>		m_descriptorSetLayout[PIPELINE_CACHE_NDX_COUNT];
1134 	Move<VkDescriptorSet>			m_descriptorSet[PIPELINE_CACHE_NDX_COUNT];
1135 
1136 	Move<VkPipelineLayout>			m_pipelineLayout[PIPELINE_CACHE_NDX_COUNT];
1137 };
1138 
initPrograms(SourceCollections & programCollection) const1139 void ComputeExecutablePropertiesTest::initPrograms (SourceCollections& programCollection) const
1140 {
1141 	programCollection.glslSources.add("basic_compute") << glu::ComputeSource(
1142 		"#version 310 es\n"
1143 		"layout(local_size_x = 1) in;\n"
1144 		"layout(std430) buffer;\n"
1145 		"layout(binding = 0) readonly buffer Input0\n"
1146 		"{\n"
1147 		"  vec4 elements[];\n"
1148 		"} input_data0;\n"
1149 		"layout(binding = 1) writeonly buffer Output\n"
1150 		"{\n"
1151 		"  vec4 elements[];\n"
1152 		"} output_data;\n"
1153 		"void main()\n"
1154 		"{\n"
1155 		"  uint ident = gl_GlobalInvocationID.x;\n"
1156 		"  output_data.elements[ident] = input_data0.elements[ident] * input_data0.elements[ident];\n"
1157 		"}");
1158 }
1159 
createInstance(Context & context) const1160 TestInstance* ComputeExecutablePropertiesTest::createInstance (Context& context) const
1161 {
1162 	return new ComputeExecutablePropertiesTestInstance(context, &m_param);
1163 }
1164 
buildDescriptorSets(deUint32 ndx)1165 void ComputeExecutablePropertiesTestInstance::buildDescriptorSets (deUint32 ndx)
1166 {
1167 	const DeviceInterface&	vk				= m_context.getDeviceInterface();
1168 	const VkDevice			vkDevice		= m_context.getDevice();
1169 
1170 	// Create descriptor set layout
1171 	DescriptorSetLayoutBuilder descLayoutBuilder;
1172 	for (deUint32 bindingNdx = 0u; bindingNdx < 2u; bindingNdx++)
1173 		descLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
1174 	m_descriptorSetLayout[ndx] = descLayoutBuilder.build(vk, vkDevice);
1175 }
1176 
buildShader(deUint32 ndx)1177 void ComputeExecutablePropertiesTestInstance::buildShader (deUint32 ndx)
1178 {
1179 	const DeviceInterface&	vk				= m_context.getDeviceInterface();
1180 	const VkDevice			vkDevice		= m_context.getDevice();
1181 
1182 	// Create compute shader
1183 	VkShaderModuleCreateInfo shaderModuleCreateInfo =
1184 	{
1185 		VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,									// VkStructureType				sType;
1186 		DE_NULL,																		// const void*					pNext;
1187 		0u,																				// VkShaderModuleCreateFlags	flags;
1188 		m_context.getBinaryCollection().get("basic_compute").getSize(),					// deUintptr					codeSize;
1189 		(deUint32*)m_context.getBinaryCollection().get("basic_compute").getBinary(),	// const deUint32*				pCode;
1190 	};
1191 	m_computeShaderModule[ndx] = createShaderModule(vk, vkDevice, &shaderModuleCreateInfo);
1192 }
1193 
buildPipeline(deUint32 ndx)1194 void ComputeExecutablePropertiesTestInstance::buildPipeline (deUint32 ndx)
1195 {
1196 	const DeviceInterface&	vk				 = m_context.getDeviceInterface();
1197 	const VkDevice			vkDevice		 = m_context.getDevice();
1198 
1199 	// Create compute pipeline layout
1200 	const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
1201 	{
1202 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,					// VkStructureType					sType;
1203 		DE_NULL,														// const void*						pNext;
1204 		0u,																// VkPipelineLayoutCreateFlags		flags;
1205 		1u,																// deUint32							setLayoutCount;
1206 		&m_descriptorSetLayout[ndx].get(),								// const VkDescriptorSetLayout*		pSetLayouts;
1207 		0u,																// deUint32							pushConstantRangeCount;
1208 		DE_NULL,														// const VkPushConstantRange*		pPushConstantRanges;
1209 	};
1210 
1211 	m_pipelineLayout[ndx] = createPipelineLayout(vk, vkDevice, &pipelineLayoutCreateInfo);
1212 
1213 	const VkPipelineShaderStageCreateInfo stageCreateInfo =
1214 	{
1215 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,			// VkStructureType					sType;
1216 		DE_NULL,														// const void*						pNext;
1217 		0u,																// VkPipelineShaderStageCreateFlags	flags;
1218 		VK_SHADER_STAGE_COMPUTE_BIT,									// VkShaderStageFlagBits			stage;
1219 		*m_computeShaderModule[ndx],									// VkShaderModule					module;
1220 		"main",															// const char*						pName;
1221 		DE_NULL,														// const VkSpecializationInfo*		pSpecializationInfo;
1222 	};
1223 
1224 	VkPipelineCreateFlags flags = 0;
1225 	if (m_param->getTestStatistics())
1226 	{
1227 		flags |= VK_PIPELINE_CREATE_CAPTURE_STATISTICS_BIT_KHR;
1228 	}
1229 
1230 	// Only check gather internal representations on the second
1231 	// pipeline.  This way, it's more obvious if they failed to capture
1232 	// due to the pipeline being cached.
1233 	if (ndx == PIPELINE_CACHE_NDX_CACHED && m_param->getTestInternalRepresentations())
1234 	{
1235 		flags |= VK_PIPELINE_CREATE_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR;
1236 	}
1237 
1238 	const VkComputePipelineCreateInfo pipelineCreateInfo =
1239 	{
1240 		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,				// VkStructureType					sType;
1241 		DE_NULL,													// const void*						pNext;
1242 		flags,														// VkPipelineCreateFlags			flags;
1243 		stageCreateInfo,											// VkPipelineShaderStageCreateInfo	stage;
1244 		*m_pipelineLayout[ndx],										// VkPipelineLayout					layout;
1245 		(VkPipeline)0,												// VkPipeline						basePipelineHandle;
1246 		0u,															// deInt32							basePipelineIndex;
1247 	};
1248 
1249 	m_pipeline[ndx] = createComputePipeline(vk, vkDevice, *m_cache, &pipelineCreateInfo, DE_NULL);
1250 }
1251 
ComputeExecutablePropertiesTestInstance(Context & context,const ExecutablePropertiesTestParam * param)1252 ComputeExecutablePropertiesTestInstance::ComputeExecutablePropertiesTestInstance (Context&				context,
1253 													const ExecutablePropertiesTestParam*	param)
1254 	: ExecutablePropertiesTestInstance (context, param)
1255 {
1256 	for (deUint32 ndx = 0; ndx < PIPELINE_CACHE_NDX_COUNT; ndx++)
1257 	{
1258 		buildDescriptorSets(ndx);
1259 		buildShader(ndx);
1260 		buildPipeline(ndx);
1261 	}
1262 }
1263 
~ComputeExecutablePropertiesTestInstance(void)1264 ComputeExecutablePropertiesTestInstance::~ComputeExecutablePropertiesTestInstance (void)
1265 {
1266 }
1267 
1268 } // anonymous
1269 
createExecutablePropertiesTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)1270 tcu::TestCaseGroup* createExecutablePropertiesTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
1271 {
1272 
1273 	de::MovePtr<tcu::TestCaseGroup> binaryInfoTests (new tcu::TestCaseGroup(testCtx, "executable_properties", "pipeline binary statistics tests"));
1274 
1275 	// Graphics Pipeline Tests
1276 	{
1277 		de::MovePtr<tcu::TestCaseGroup> graphicsTests (new tcu::TestCaseGroup(testCtx, "graphics", "Test pipeline binary info with graphics pipeline."));
1278 
1279 		const VkShaderStageFlags vertFragStages		= VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
1280 		const VkShaderStageFlags vertGeomFragStages	= vertFragStages | VK_SHADER_STAGE_GEOMETRY_BIT;
1281 		const VkShaderStageFlags vertTessFragStages	= vertFragStages | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
1282 
1283 		const ExecutablePropertiesTestParam testParams[]
1284 		{
1285 			{ pipelineConstructionType, vertFragStages,		DE_FALSE, DE_FALSE },
1286 			{ pipelineConstructionType, vertGeomFragStages,	DE_FALSE, DE_FALSE },
1287 			{ pipelineConstructionType, vertTessFragStages,	DE_FALSE, DE_FALSE },
1288 			{ pipelineConstructionType, vertFragStages,		DE_TRUE, DE_FALSE },
1289 			{ pipelineConstructionType, vertGeomFragStages,	DE_TRUE, DE_FALSE },
1290 			{ pipelineConstructionType, vertTessFragStages,	DE_TRUE, DE_FALSE },
1291 			{ pipelineConstructionType, vertFragStages,		DE_FALSE, DE_TRUE },
1292 			{ pipelineConstructionType, vertGeomFragStages,	DE_FALSE, DE_TRUE },
1293 			{ pipelineConstructionType, vertTessFragStages,	DE_FALSE, DE_TRUE },
1294 			{ pipelineConstructionType, vertFragStages,		DE_TRUE, DE_TRUE },
1295 			{ pipelineConstructionType, vertGeomFragStages,	DE_TRUE, DE_TRUE },
1296 			{ pipelineConstructionType, vertTessFragStages,	DE_TRUE, DE_TRUE },
1297 		};
1298 
1299 		for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1300 			graphicsTests->addChild(newTestCase<GraphicsExecutablePropertiesTest>(testCtx, &testParams[i]));
1301 
1302 		binaryInfoTests->addChild(graphicsTests.release());
1303 	}
1304 
1305 	// Compute Pipeline Tests - don't repeat those tests for graphics pipeline library
1306 	if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1307 	{
1308 		de::MovePtr<tcu::TestCaseGroup> computeTests (new tcu::TestCaseGroup(testCtx, "compute", "Test pipeline binary info with compute pipeline."));
1309 
1310 		const ExecutablePropertiesTestParam testParams[]
1311 		{
1312 			{ pipelineConstructionType, VK_SHADER_STAGE_COMPUTE_BIT, DE_FALSE, DE_FALSE },
1313 			{ pipelineConstructionType, VK_SHADER_STAGE_COMPUTE_BIT, DE_TRUE, DE_FALSE },
1314 			{ pipelineConstructionType, VK_SHADER_STAGE_COMPUTE_BIT, DE_FALSE, DE_TRUE },
1315 			{ pipelineConstructionType, VK_SHADER_STAGE_COMPUTE_BIT, DE_TRUE, DE_TRUE },
1316 		};
1317 
1318 		for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(testParams); i++)
1319 			computeTests->addChild(newTestCase<ComputeExecutablePropertiesTest>(testCtx, &testParams[i]));
1320 
1321 		binaryInfoTests->addChild(computeTests.release());
1322 	}
1323 
1324 	return binaryInfoTests.release();
1325 }
1326 
1327 } // pipeline
1328 
1329 } // vkt
1330