• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 ARM Ltd.
7  * Copyright (c) 2023 LunarG, Inc.
8  * Copyright (c) 2023 Nintendo
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Timestamp Tests
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktPipelineTimestampTests.hpp"
28 #include "vktPipelineClearUtil.hpp"
29 #include "vktPipelineImageUtil.hpp"
30 #include "vktPipelineVertexUtil.hpp"
31 #include "vktPipelineReferenceRenderer.hpp"
32 #include "vktCustomInstancesDevices.hpp"
33 #include "vktTestCaseUtil.hpp"
34 #include "vkSafetyCriticalUtil.hpp"
35 #include "vkImageUtil.hpp"
36 #include "vkMemUtil.hpp"
37 #include "vkPrograms.hpp"
38 #include "vkBuilderUtil.hpp"
39 #include "vkQueryUtil.hpp"
40 #include "vkRef.hpp"
41 #include "vkRefUtil.hpp"
42 #include "vkTypeUtil.hpp"
43 #include "vkCmdUtil.hpp"
44 #include "vkObjUtil.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuCommandLine.hpp"
47 #include "deUniquePtr.hpp"
48 #include "deStringUtil.hpp"
49 #include "deMemory.h"
50 
51 #include <sstream>
52 #include <vector>
53 #include <set>
54 #include <cctype>
55 #include <locale>
56 #include <limits>
57 #include <thread>
58 #include <chrono>
59 #include <time.h>
60 #include <algorithm>
61 
62 #if (DE_OS == DE_OS_WIN32)
63 #	define VC_EXTRALEAN
64 #	define WIN32_LEAN_AND_MEAN
65 #	define NOMINMAX
66 #	include <windows.h>
67 #endif
68 
69 namespace vkt
70 {
71 namespace pipeline
72 {
73 
74 using namespace vk;
75 
76 namespace
77 {
78 typedef std::vector<VkPipelineStageFlagBits> StageFlagVector;
79 
80 // helper functions
81 #define GEN_DESC_STRING(name,postfix)                                      \
82 		do {                                                               \
83 		   for (std::string::size_type ndx = 0; ndx<strlen(#name); ++ndx)  \
84 			 if(isDescription && #name[ndx] == '_')                        \
85 			   desc << " ";                                                \
86 			 else                                                          \
87 			   desc << std::tolower(#name[ndx],loc);                       \
88 		   if (isDescription)                                              \
89 			 desc << " " << #postfix;                                      \
90 		   else                                                            \
91 			 desc << "_" << #postfix;                                      \
92 		} while (deGetFalse())
93 
getPipelineStageFlagStr(const VkPipelineStageFlagBits stage,bool isDescription)94 std::string getPipelineStageFlagStr (const VkPipelineStageFlagBits stage,
95 									 bool                          isDescription)
96 {
97 	std::ostringstream desc;
98 	std::locale loc;
99 	switch(stage)
100 	{
101 #define STAGE_CASE(p)                              \
102 		case VK_PIPELINE_STAGE_##p##_BIT:          \
103 		{                                          \
104 			GEN_DESC_STRING(p, stage);             \
105 			break;                                 \
106 		}
107 		STAGE_CASE(TOP_OF_PIPE)
108 		STAGE_CASE(DRAW_INDIRECT)
109 		STAGE_CASE(VERTEX_INPUT)
110 		STAGE_CASE(VERTEX_SHADER)
111 		STAGE_CASE(TESSELLATION_CONTROL_SHADER)
112 		STAGE_CASE(TESSELLATION_EVALUATION_SHADER)
113 		STAGE_CASE(GEOMETRY_SHADER)
114 		STAGE_CASE(FRAGMENT_SHADER)
115 		STAGE_CASE(EARLY_FRAGMENT_TESTS)
116 		STAGE_CASE(LATE_FRAGMENT_TESTS)
117 		STAGE_CASE(COLOR_ATTACHMENT_OUTPUT)
118 		STAGE_CASE(COMPUTE_SHADER)
119 		STAGE_CASE(TRANSFER)
120 		STAGE_CASE(HOST)
121 		STAGE_CASE(ALL_GRAPHICS)
122 		STAGE_CASE(ALL_COMMANDS)
123 #undef STAGE_CASE
124 	  default:
125 		desc << "unknown stage!";
126 		DE_FATAL("Unknown Stage!");
127 		break;
128 	}
129 
130 	return desc.str();
131 }
132 
133 enum TransferMethod
134 {
135 	TRANSFER_METHOD_COPY_BUFFER = 0,
136 	TRANSFER_METHOD_COPY_IMAGE,
137 	TRANSFER_METHOD_BLIT_IMAGE,
138 	TRANSFER_METHOD_COPY_BUFFER_TO_IMAGE,
139 	TRANSFER_METHOD_COPY_IMAGE_TO_BUFFER,
140 	TRANSFER_METHOD_UPDATE_BUFFER,
141 	TRANSFER_METHOD_FILL_BUFFER,
142 	TRANSFER_METHOD_CLEAR_COLOR_IMAGE,
143 	TRANSFER_METHOD_CLEAR_DEPTH_STENCIL_IMAGE,
144 	TRANSFER_METHOD_RESOLVE_IMAGE,
145 	TRANSFER_METHOD_COPY_QUERY_POOL_RESULTS,
146 	TRANSFER_METHOD_COPY_QUERY_POOL_RESULTS_STRIDE_ZERO,
147 	TRANSFER_METHOD_LAST
148 };
149 
getTransferMethodStr(const TransferMethod method,bool isDescription)150 std::string getTransferMethodStr (const TransferMethod	method,
151 								  bool					isDescription)
152 {
153 	std::ostringstream	desc;
154 	std::locale			loc;
155 
156 	switch(method)
157 	{
158 #define METHOD_CASE(p)                             \
159 		case TRANSFER_METHOD_##p:                  \
160 		{                                          \
161 			GEN_DESC_STRING(p, method);            \
162 			break;                                 \
163 		}
164 	  METHOD_CASE(COPY_BUFFER)
165 	  METHOD_CASE(COPY_IMAGE)
166 	  METHOD_CASE(BLIT_IMAGE)
167 	  METHOD_CASE(COPY_BUFFER_TO_IMAGE)
168 	  METHOD_CASE(COPY_IMAGE_TO_BUFFER)
169 	  METHOD_CASE(UPDATE_BUFFER)
170 	  METHOD_CASE(FILL_BUFFER)
171 	  METHOD_CASE(CLEAR_COLOR_IMAGE)
172 	  METHOD_CASE(CLEAR_DEPTH_STENCIL_IMAGE)
173 	  METHOD_CASE(RESOLVE_IMAGE)
174 	  METHOD_CASE(COPY_QUERY_POOL_RESULTS)
175 	  METHOD_CASE(COPY_QUERY_POOL_RESULTS_STRIDE_ZERO)
176 #undef METHOD_CASE
177 	  default:
178 		desc << "unknown method!";
179 		DE_FATAL("Unknown method!");
180 		break;
181 	}
182 
183 	return desc.str();
184 }
185 
186 constexpr deUint32 MIN_TIMESTAMP_VALID_BITS = 36;
187 constexpr deUint32 MAX_TIMESTAMP_VALID_BITS = 64;
188 
189 // Checks the number of valid bits for the given queue meets the spec requirements.
checkValidBits(deUint32 validBits,deUint32 queueFamilyIndex)190 void checkValidBits (deUint32 validBits, deUint32 queueFamilyIndex)
191 {
192 	if (validBits < MIN_TIMESTAMP_VALID_BITS || validBits > MAX_TIMESTAMP_VALID_BITS)
193 	{
194 		std::ostringstream msg;
195 		msg << "Invalid value for timestampValidBits (" << validBits << ") in queue index " << queueFamilyIndex;
196 		TCU_FAIL(msg.str());
197 	}
198 }
199 
200 // Returns the timestamp mask given the number of valid timestamp bits.
timestampMaskFromValidBits(deUint32 validBits)201 deUint64 timestampMaskFromValidBits (deUint32 validBits)
202 {
203 	return ((validBits == MAX_TIMESTAMP_VALID_BITS) ? std::numeric_limits<deUint64>::max() : ((1ULL << validBits) - 1));
204 }
205 
206 // Checks support for timestamps and returns the timestamp mask.
checkTimestampsSupported(const InstanceInterface & vki,const VkPhysicalDevice physDevice,const deUint32 queueFamilyIndex)207 deUint64 checkTimestampsSupported (const InstanceInterface& vki, const VkPhysicalDevice physDevice, const deUint32 queueFamilyIndex)
208 {
209 	const std::vector<VkQueueFamilyProperties>	queueProperties		= vk::getPhysicalDeviceQueueFamilyProperties(vki, physDevice);
210 	DE_ASSERT(queueFamilyIndex < queueProperties.size());
211 	const deUint32&								validBits			= queueProperties[queueFamilyIndex].timestampValidBits;
212 
213 	if (validBits == 0)
214 		throw tcu::NotSupportedError("Queue does not support timestamps");
215 
216 	checkValidBits(validBits, queueFamilyIndex);
217 	return timestampMaskFromValidBits(validBits);
218 }
219 
checkTimestampBits(deUint64 timestamp,deUint64 mask)220 void checkTimestampBits (deUint64 timestamp, deUint64 mask)
221 {
222 	// The spec says:
223 	// timestampValidBits is the unsigned integer count of meaningful bits in
224 	// the timestamps written via vkCmdWriteTimestamp. The valid range for the
225 	// count is 36..64 bits, or a value of 0, indicating no support for
226 	// timestamps. Bits outside the valid range are guaranteed to be zeros.
227 	if (timestamp > mask)
228 	{
229 		std::ostringstream msg;
230 		msg << std::hex << "Invalid device timestamp value 0x" << timestamp << " according to device timestamp mask 0x" << mask;
231 		TCU_FAIL(msg.str());
232 	}
233 }
234 
235 // helper classes
236 class TimestampTestParam
237 {
238 public:
239 								TimestampTestParam		(const PipelineConstructionType	pipelineConstructionType,
240 														 const VkPipelineStageFlagBits*	stages,
241 														 const deUint32					stageCount,
242 														 const bool						inRenderPass,
243 														 const bool						hostQueryReset,
244 														 const bool						transferOnlyQueue,
245 														 const VkQueryResultFlags		queryResultFlags);
246 								~TimestampTestParam			(void);
247 	virtual const std::string	generateTestName			(void) const;
getPipelineConstructionType(void) const248 	PipelineConstructionType	getPipelineConstructionType	(void) const	{ return m_pipelineConstructionType; }
getStageVector(void) const249 	StageFlagVector				getStageVector				(void) const	{ return m_stageVec; }
getInRenderPass(void) const250 	bool						getInRenderPass				(void) const	{ return m_inRenderPass; }
getHostQueryReset(void) const251 	bool						getHostQueryReset			(void) const	{ return m_hostQueryReset; }
getTransferOnlyQueue(void) const252 	bool						getTransferOnlyQueue		(void) const	{ return m_transferOnlyQueue; }
getQueryResultFlags(void) const253 	VkQueryResultFlags			getQueryResultFlags			(void) const	{ return m_queryResultFlags; }
toggleInRenderPass(void)254 	void						toggleInRenderPass			(void)			{ m_inRenderPass = !m_inRenderPass; }
toggleHostQueryReset(void)255 	void						toggleHostQueryReset		(void)			{ m_hostQueryReset = !m_hostQueryReset; }
256 
setQueryResultFlags(VkQueryResultFlags flags)257 	void						setQueryResultFlags		(VkQueryResultFlags flags)	{ m_queryResultFlags = flags; }
258 
259 protected:
260 	const PipelineConstructionType	m_pipelineConstructionType;
261 	StageFlagVector					m_stageVec;
262 	bool							m_inRenderPass;
263 	bool							m_hostQueryReset;
264 	bool							m_transferOnlyQueue;
265 	VkQueryResultFlags				m_queryResultFlags;
266 };
267 
TimestampTestParam(const PipelineConstructionType pipelineConstructionType,const VkPipelineStageFlagBits * stages,const deUint32 stageCount,const bool inRenderPass,const bool hostQueryReset,const bool transferOnlyQueue,const VkQueryResultFlags queryResultFlags)268 TimestampTestParam::TimestampTestParam (const PipelineConstructionType	pipelineConstructionType,
269 										const VkPipelineStageFlagBits*	stages,
270 										const deUint32					stageCount,
271 										const bool						inRenderPass,
272 										const bool						hostQueryReset,
273 										const bool						transferOnlyQueue,
274 										const VkQueryResultFlags		queryResultFlags)
275 	: m_pipelineConstructionType(pipelineConstructionType)
276 	, m_inRenderPass(inRenderPass)
277 	, m_hostQueryReset(hostQueryReset)
278 	, m_transferOnlyQueue(transferOnlyQueue)
279 	, m_queryResultFlags(queryResultFlags)
280 {
281 	for (deUint32 ndx = 0; ndx < stageCount; ndx++)
282 	{
283 		m_stageVec.push_back(stages[ndx]);
284 	}
285 }
286 
~TimestampTestParam(void)287 TimestampTestParam::~TimestampTestParam (void)
288 {
289 }
290 
generateTestName(void) const291 const std::string TimestampTestParam::generateTestName (void) const
292 {
293 	std::string result("");
294 
295 	for (StageFlagVector::const_iterator it = m_stageVec.begin(); it != m_stageVec.end(); it++)
296 	{
297 		if(*it != VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT)
298 		{
299 			result += getPipelineStageFlagStr(*it, false) + '_';
300 		}
301 	}
302 	if(m_inRenderPass)
303 		result += "in_render_pass";
304 	else
305 		result += "out_of_render_pass";
306 
307 	if(m_hostQueryReset)
308 		result += "_host_query_reset";
309 
310 	if (m_transferOnlyQueue)
311 		result += "_transfer_queue";
312 
313 	if (m_queryResultFlags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
314 		result += "_with_availability_bit";
315 
316 	return result;
317 }
318 
319 class TransferTimestampTestParam : public TimestampTestParam
320 {
321 public:
322 						TransferTimestampTestParam	(const PipelineConstructionType	pipelineConstructionType,
323 													 const VkPipelineStageFlagBits*	stages,
324 													 const deUint32					stageCount,
325 													 const bool						inRenderPass,
326 													 const bool						hostQueryReset,
327 													 const bool						transferOnlyQueue,
328 													 const deUint32					methodNdx,
329 													 const VkQueryResultFlags		flags);
~TransferTimestampTestParam(void)330 						~TransferTimestampTestParam	(void) { }
331 	const std::string	generateTestName			(void) const;
332 	const std::string	generateTestDescription		(void) const;
getMethod(void) const333 	TransferMethod		getMethod					(void) const { return m_method; }
334 protected:
335 	TransferMethod		m_method;
336 };
337 
TransferTimestampTestParam(const PipelineConstructionType pipelineConstructionType,const VkPipelineStageFlagBits * stages,const deUint32 stageCount,const bool inRenderPass,const bool hostQueryReset,const bool transferOnlyQueue,const deUint32 methodNdx,const VkQueryResultFlags flags)338 TransferTimestampTestParam::TransferTimestampTestParam (const PipelineConstructionType	pipelineConstructionType,
339 														const VkPipelineStageFlagBits*	stages,
340 														const deUint32					stageCount,
341 														const bool						inRenderPass,
342 														const bool						hostQueryReset,
343 														const bool						transferOnlyQueue,
344 														const deUint32					methodNdx,
345 														const VkQueryResultFlags		flags)
346 	: TimestampTestParam(pipelineConstructionType, stages, stageCount, inRenderPass, hostQueryReset, transferOnlyQueue, flags)
347 {
348 	DE_ASSERT(methodNdx < (deUint32)TRANSFER_METHOD_LAST);
349 
350 	m_method = (TransferMethod)methodNdx;
351 }
352 
generateTestName(void) const353 const std::string TransferTimestampTestParam::generateTestName (void) const
354 {
355 	std::string result("");
356 
357 	for (StageFlagVector::const_iterator it = m_stageVec.begin(); it != m_stageVec.end(); it++)
358 	{
359 		if(*it != VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT)
360 		{
361 			result += getPipelineStageFlagStr(*it, false) + '_';
362 		}
363 	}
364 
365 	result += "with_" + getTransferMethodStr(m_method, false);
366 
367 	if(m_hostQueryReset)
368 		result += "_host_query_reset";
369 
370 	if (m_transferOnlyQueue)
371 		result += "_transfer_queue";
372 
373 	if (m_queryResultFlags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT)
374 		result += "_with_availability_bit";
375 
376 	return result;
377 }
378 
379 class TwoCmdBuffersTestParam : public TimestampTestParam
380 {
381 public:
382 							TwoCmdBuffersTestParam	(const PipelineConstructionType	pipelineConstructionType,
383 													 const VkPipelineStageFlagBits*	stages,
384 													 const deUint32					stageCount,
385 													 const bool						inRenderPass,
386 													 const bool						hostQueryReset,
387 													 const bool						transferOnlyQueue,
388 													 const VkCommandBufferLevel		cmdBufferLevel,
389 													 const VkQueryResultFlags		queryPoolResultFlags);
~TwoCmdBuffersTestParam(void)390 							~TwoCmdBuffersTestParam	(void) { }
getCmdBufferLevel(void) const391 	VkCommandBufferLevel	getCmdBufferLevel		(void) const { return m_cmdBufferLevel; }
392 protected:
393 	VkCommandBufferLevel	m_cmdBufferLevel;
394 };
395 
TwoCmdBuffersTestParam(const PipelineConstructionType pipelineConstructionType,const VkPipelineStageFlagBits * stages,const deUint32 stageCount,const bool inRenderPass,const bool hostQueryReset,const bool transferOnlyQueue,const VkCommandBufferLevel cmdBufferLevel,const VkQueryResultFlags queryPoolResultFlags)396 TwoCmdBuffersTestParam::TwoCmdBuffersTestParam	(const PipelineConstructionType	pipelineConstructionType,
397 												 const VkPipelineStageFlagBits*	stages,
398 												 const deUint32					stageCount,
399 												 const bool						inRenderPass,
400 												 const bool						hostQueryReset,
401 												 const bool						transferOnlyQueue,
402 												 const VkCommandBufferLevel		cmdBufferLevel,
403 												 const VkQueryResultFlags		queryPoolResultFlags)
404 	: TimestampTestParam(pipelineConstructionType, stages, stageCount, inRenderPass, hostQueryReset, transferOnlyQueue, queryPoolResultFlags)
405 	, m_cmdBufferLevel(cmdBufferLevel)
406 {
407 }
408 
409 template <class Test>
newTestCase(tcu::TestContext & testContext,TimestampTestParam * testParam)410 vkt::TestCase* newTestCase	(tcu::TestContext&		testContext,
411 							 TimestampTestParam*	testParam)
412 {
413 	return new Test(testContext,
414 					testParam->generateTestName().c_str(),
415 					testParam);
416 }
417 
418 // Test Classes
419 class TimestampTest : public vkt::TestCase
420 {
421 public:
422 	enum
423 	{
424 		ENTRY_COUNT = 8
425 	};
426 
TimestampTest(tcu::TestContext & testContext,const std::string & name,const TimestampTestParam * param)427 							TimestampTest	(tcu::TestContext&			testContext,
428 											 const std::string&			name,
429 											 const TimestampTestParam*	param)
430 											 : vkt::TestCase				(testContext, name)
431 											 , m_pipelineConstructionType	(param->getPipelineConstructionType())
432 											 , m_stages						(param->getStageVector())
433 											 , m_inRenderPass				(param->getInRenderPass())
434 											 , m_hostQueryReset				(param->getHostQueryReset())
435 											 , m_transferOnlyQueue			(param->getTransferOnlyQueue())
436 											 , m_queryResultFlags			(param->getQueryResultFlags())
437 											 { }
~TimestampTest(void)438 	virtual					~TimestampTest	(void) { }
439 	virtual void			initPrograms	(SourceCollections& programCollection) const;
440 	virtual TestInstance*	createInstance	(Context& context) const;
441 	virtual void			checkSupport	(Context& context) const;
442 protected:
443 	const PipelineConstructionType	m_pipelineConstructionType;
444 	const StageFlagVector			m_stages;
445 	const bool						m_inRenderPass;
446 	const bool						m_hostQueryReset;
447 	const bool						m_transferOnlyQueue;
448 	const VkQueryResultFlags		m_queryResultFlags;
449 };
450 
451 class TimestampTestInstance : public vkt::TestInstance
452 {
453 public:
454 							TimestampTestInstance		(Context&						context,
455 														 const StageFlagVector&			stages,
456 														 const bool						inRenderPass,
457 														 const bool						hostQueryReset,
458 														 const bool						transferOnlyQueue,
459 														 const VkQueryResultFlags		queryResultFlags);
460 
461 	virtual					~TimestampTestInstance		(void);
462 	virtual tcu::TestStatus	iterate						(void);
463 
464 protected:
465 	virtual tcu::TestStatus	verifyTimestamp				(void);
466 	virtual void			buildPipeline				(void);
467 	virtual void			configCommandBuffer			(void);
468 
469 	Move<VkBuffer>			createBufferAndBindMemory	(VkDeviceSize				size,
470 														 VkBufferUsageFlags			usage,
471 														 de::MovePtr<Allocation>*	pAlloc);
472 
473 	Move<VkImage>			createImage2DAndBindMemory	(VkFormat					format,
474 														 deUint32					width,
475 														 deUint32					height,
476 														 VkImageUsageFlags			usage,
477 														 VkSampleCountFlagBits		sampleCount,
478 														 de::MovePtr<Allocation>*	pAlloc);
479 
480 	// Creates a device that has transfer only operations
481 	void					createCustomDeviceWithTransferOnlyQueue (void);
482 
483 protected:
484 
485 	Move<VkDevice>			m_customDevice;
486 	de::MovePtr<Allocator>	m_customAllocator;
487 
488 	VkDevice				m_device;
489 	Allocator*				m_allocator;
490 	uint32_t				m_queueFamilyIndex;
491 
492 	const StageFlagVector	m_stages;
493 	bool					m_inRenderPass;
494 	bool					m_hostQueryReset;
495 	bool					m_transferOnlyQueue;
496 	VkQueryResultFlags		m_queryResultFlags;
497 
498 	Move<VkCommandPool>		m_cmdPool;
499 	Move<VkCommandBuffer>	m_cmdBuffer;
500 	Move<VkQueryPool>		m_queryPool;
501 	deUint64*				m_timestampValues;
502 	deUint64*				m_timestampValuesHostQueryReset;
503 	deUint64				m_timestampMask;
504 };
505 
initPrograms(SourceCollections & programCollection) const506 void TimestampTest::initPrograms (SourceCollections& programCollection) const
507 {
508 	vkt::TestCase::initPrograms(programCollection);
509 }
510 
checkSupport(Context & context) const511 void TimestampTest::checkSupport (Context& context) const
512 {
513 	const InstanceInterface&	vki					= context.getInstanceInterface();
514 	const VkPhysicalDevice		physicalDevice		= context.getPhysicalDevice();
515 	deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
516 
517 	if (m_transferOnlyQueue)
518 		queueFamilyIndex = findQueueFamilyIndexWithCaps(vki, physicalDevice, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT);
519 
520 	// Check support for timestamp queries
521 	const std::vector<VkQueueFamilyProperties> queueProperties = vk::getPhysicalDeviceQueueFamilyProperties(context.getInstanceInterface(), context.getPhysicalDevice());
522 	DE_ASSERT(queueFamilyIndex < (deUint32)queueProperties.size());
523 	if (!queueProperties[queueFamilyIndex].timestampValidBits)
524 		throw tcu::NotSupportedError("Universal queue does not support timestamps");
525 
526 	if (m_hostQueryReset)
527 	{
528 		// Check VK_EXT_host_query_reset is supported
529 		context.requireDeviceFunctionality("VK_EXT_host_query_reset");
530 
531 		if(context.getHostQueryResetFeatures().hostQueryReset == VK_FALSE)
532 			throw tcu::NotSupportedError("Implementation doesn't support resetting queries from the host");
533 	}
534 	checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType);
535 }
536 
createInstance(Context & context) const537 TestInstance* TimestampTest::createInstance (Context& context) const
538 {
539 	return new TimestampTestInstance(context, m_stages, m_inRenderPass, m_hostQueryReset, false, m_queryResultFlags);
540 }
541 
TimestampTestInstance(Context & context,const StageFlagVector & stages,const bool inRenderPass,const bool hostQueryReset,const bool transferOnlyQueue,const VkQueryResultFlags queryResultFlags)542 TimestampTestInstance::TimestampTestInstance (Context&						context,
543 											  const StageFlagVector&		stages,
544 											  const bool					inRenderPass,
545 											  const bool					hostQueryReset,
546 											  const bool					transferOnlyQueue,
547 											  const VkQueryResultFlags		queryResultFlags)
548 	: TestInstance			(context)
549 	, m_stages				(stages)
550 	, m_inRenderPass		(inRenderPass)
551 	, m_hostQueryReset		(hostQueryReset)
552 	, m_transferOnlyQueue	(transferOnlyQueue)
553 	, m_queryResultFlags	(queryResultFlags)
554 {
555 	const DeviceInterface& vk = context.getDeviceInterface();
556 
557 	m_device			= context.getDevice();
558 	m_allocator			= &context.getDefaultAllocator();
559 	m_queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
560 
561 	// when needed create custom device and overwrite m_device, m_allocator and m_queueFamilyIndex
562 	if (m_transferOnlyQueue)
563 		createCustomDeviceWithTransferOnlyQueue();
564 
565 	m_timestampMask = checkTimestampsSupported(context.getInstanceInterface(), context.getPhysicalDevice(), m_queueFamilyIndex);
566 
567 	// Create Query Pool
568 	{
569 		const VkQueryPoolCreateInfo queryPoolParams =
570 		{
571 		   VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,	// VkStructureType               sType;
572 		   DE_NULL,										// const void*                   pNext;
573 		   0u,											// VkQueryPoolCreateFlags        flags;
574 		   VK_QUERY_TYPE_TIMESTAMP,						// VkQueryType                   queryType;
575 		   TimestampTest::ENTRY_COUNT,					// deUint32                      entryCount;
576 		   0u,											// VkQueryPipelineStatisticFlags pipelineStatistics;
577 		};
578 
579 		m_queryPool = createQueryPool(vk, m_device, &queryPoolParams);
580 	}
581 
582 	// Create command pool
583 	m_cmdPool = createCommandPool(vk, m_device, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, m_queueFamilyIndex);
584 
585 	// Create command buffer
586 	m_cmdBuffer = allocateCommandBuffer(vk, m_device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
587 
588 	// alloc timestamp values
589 	m_timestampValues = new deUint64[m_stages.size() * ((m_queryResultFlags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) ? 2u : 1u)];
590 
591 	if (m_hostQueryReset)
592 		m_timestampValuesHostQueryReset = new deUint64[m_stages.size() * 2];
593 	else
594 		m_timestampValuesHostQueryReset = DE_NULL;
595 }
596 
~TimestampTestInstance(void)597 TimestampTestInstance::~TimestampTestInstance (void)
598 {
599 	delete[] m_timestampValues;
600 	m_timestampValues = NULL;
601 
602 	delete[] m_timestampValuesHostQueryReset;
603 	m_timestampValuesHostQueryReset = NULL;
604 }
605 
buildPipeline(void)606 void TimestampTestInstance::buildPipeline (void)
607 {
608 }
609 
configCommandBuffer(void)610 void TimestampTestInstance::configCommandBuffer (void)
611 {
612 	const DeviceInterface& vk = m_context.getDeviceInterface();
613 
614 	beginCommandBuffer(vk, *m_cmdBuffer, 0u);
615 
616 	if (!m_hostQueryReset)
617 		vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
618 
619 	deUint32 timestampEntry = 0;
620 	for (const auto& stage : m_stages)
621 	{
622 		vk.cmdWriteTimestamp(*m_cmdBuffer, stage, *m_queryPool, timestampEntry++);
623 	}
624 
625 	endCommandBuffer(vk, *m_cmdBuffer);
626 }
627 
iterate(void)628 tcu::TestStatus TimestampTestInstance::iterate (void)
629 {
630 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
631 	const VkQueue			queue				= getDeviceQueue(vk, m_device, m_queueFamilyIndex, 0);
632 	const bool				availabilityBit		= m_queryResultFlags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT;
633 	const deUint32			stageSize			= (deUint32)m_stages.size();
634 	const deUint32			queryDataSize		= deUint32(sizeof(deUint64) * (availabilityBit ? 2u : 1u));
635 
636 	buildPipeline();
637 	configCommandBuffer();
638 	if (m_hostQueryReset)
639 	{
640 		vk.resetQueryPool(m_device, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
641 	}
642 	submitCommandsAndWait(vk, m_device, queue, m_cmdBuffer.get());
643 
644 	// Get timestamp value from query pool
645 	VK_CHECK(vk.getQueryPoolResults(m_device, *m_queryPool, 0u, stageSize, queryDataSize * stageSize, (void*)m_timestampValues, queryDataSize, m_queryResultFlags));
646 
647 	for (deUint32 ndx = 0; ndx < stageSize; ndx++)
648 	{
649 		m_timestampValues[ndx] &= m_timestampMask;
650 		if (availabilityBit)
651 			ndx++;
652 	}
653 
654 	if(m_hostQueryReset)
655 	{
656 		// Initialize timestampValuesHostQueryReset values
657 		deMemset(m_timestampValuesHostQueryReset, 0, sizeof(deUint64) * stageSize * 2);
658 
659 		for (deUint32 ndx = 0; ndx < stageSize; ndx++)
660 		{
661 			const deUint32 ndxTimestampValue = ndx * (availabilityBit ? 2u : 1u);
662 			m_timestampValuesHostQueryReset[2 * ndx] = m_timestampValues[ndxTimestampValue];
663 		}
664 
665 		// Host resets the query pool
666 		vk.resetQueryPool(m_device, *m_queryPool, 0u, stageSize);
667 		// Get timestamp value from query pool
668 		vk::VkResult res = vk.getQueryPoolResults(m_device, *m_queryPool, 0u, stageSize, sizeof(deUint64) * stageSize * 2, (void*)m_timestampValuesHostQueryReset, sizeof(deUint64) * 2, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
669 
670 		/* From Vulkan spec:
671 		 *
672 		 * If VK_QUERY_RESULT_WAIT_BIT and VK_QUERY_RESULT_PARTIAL_BIT are both not set then no result values are written to pData
673 		 * for queries that are in the unavailable state at the time of the call, and vkGetQueryPoolResults returns VK_NOT_READY.
674 		 * However, availability state is still written to pData for those queries if VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set.
675 		 */
676 		if (res != vk::VK_NOT_READY)
677 			return tcu::TestStatus::fail("QueryPoolResults incorrect reset");
678 
679 		for (deUint32 ndx = 0; ndx < stageSize; ndx++)
680 		{
681 			const deUint32 ndxTimestampValue = ndx * (availabilityBit ? 2u : 1u);
682 			if ((m_timestampValuesHostQueryReset[2 * ndx] & m_timestampMask) != m_timestampValues[ndxTimestampValue])
683 				return tcu::TestStatus::fail("QueryPoolResults returned value was modified");
684 			if (m_timestampValuesHostQueryReset[2 * ndx + 1] != 0u)
685 				return tcu::TestStatus::fail("QueryPoolResults availability status is not zero");
686 		}
687 	}
688 
689 	return verifyTimestamp();
690 }
691 
verifyTimestamp(void)692 tcu::TestStatus TimestampTestInstance::verifyTimestamp (void)
693 {
694 	bool availabilityBit = m_queryResultFlags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT;
695 	deUint32 increment = availabilityBit ? 2u : 1u;
696 	for (deUint32 first = 0u; first < m_stages.size(); first += increment)
697 	{
698 		for (deUint32 second = 0u; second < first; second += increment)
699 		{
700 			if (availabilityBit && (m_timestampValues[first + 1u] == 0u || m_timestampValues[second + 1u] == 0u))
701 			{
702 				return tcu::TestStatus::fail("Timestamp query not available");
703 			}
704 
705 			if(m_timestampValues[first] < m_timestampValues[second])
706 			{
707 				return tcu::TestStatus::fail("Latter stage timestamp is smaller than the former stage timestamp.");
708 			}
709 		}
710 	}
711 
712 	return tcu::TestStatus::pass("Timestamp increases steadily.");
713 }
714 
createBufferAndBindMemory(VkDeviceSize size,VkBufferUsageFlags usage,de::MovePtr<Allocation> * pAlloc)715 Move<VkBuffer> TimestampTestInstance::createBufferAndBindMemory (VkDeviceSize size, VkBufferUsageFlags usage, de::MovePtr<Allocation>* pAlloc)
716 {
717 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
718 	const VkBufferCreateInfo	vertexBufferParams	=
719 	{
720 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType      sType;
721 		DE_NULL,								// const void*          pNext;
722 		0u,										// VkBufferCreateFlags  flags;
723 		size,									// VkDeviceSize         size;
724 		usage,									// VkBufferUsageFlags   usage;
725 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode        sharingMode;
726 		1u,										// deUint32             queueFamilyCount;
727 		&m_queueFamilyIndex						// const deUint32*      pQueueFamilyIndices;
728 	};
729 
730 	Move<VkBuffer> vertexBuffer = createBuffer(vk, m_device, &vertexBufferParams);
731 	de::MovePtr<Allocation> vertexBufferAlloc = m_allocator->allocate(getBufferMemoryRequirements(vk, m_device, *vertexBuffer), MemoryRequirement::HostVisible);
732 
733 	VK_CHECK(vk.bindBufferMemory(m_device, *vertexBuffer, vertexBufferAlloc->getMemory(), vertexBufferAlloc->getOffset()));
734 
735 	DE_ASSERT(pAlloc);
736 	*pAlloc = vertexBufferAlloc;
737 
738 	return vertexBuffer;
739 }
740 
createImage2DAndBindMemory(VkFormat format,deUint32 width,deUint32 height,VkImageUsageFlags usage,VkSampleCountFlagBits sampleCount,de::details::MovePtr<Allocation> * pAlloc)741 Move<VkImage> TimestampTestInstance::createImage2DAndBindMemory (VkFormat							format,
742 																 deUint32							width,
743 																 deUint32							height,
744 																 VkImageUsageFlags					usage,
745 																 VkSampleCountFlagBits				sampleCount,
746 																 de::details::MovePtr<Allocation>*	pAlloc)
747 {
748 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
749 
750 	// Optimal tiling feature check
751 	VkFormatProperties		formatProperty;
752 
753 	m_context.getInstanceInterface().getPhysicalDeviceFormatProperties(m_context.getPhysicalDevice(), format, &formatProperty);
754 
755 	if((usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) && !(formatProperty.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
756 	{
757 		// Remove color attachment usage if the optimal tiling feature does not support it
758 		usage &= ~VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
759 	}
760 	if((usage & VK_IMAGE_USAGE_STORAGE_BIT) && !(formatProperty.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT))
761 	{
762 		// Remove storage usage if the optimal tiling feature does not support it
763 		usage &= ~VK_IMAGE_USAGE_STORAGE_BIT;
764 	}
765 
766 	const VkImageCreateInfo colorImageParams =
767 	{
768 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType      sType;
769 		DE_NULL,								// const void*          pNext;
770 		0u,										// VkImageCreateFlags   flags;
771 		VK_IMAGE_TYPE_2D,						// VkImageType          imageType;
772 		format,									// VkFormat             format;
773 		{ width, height, 1u },					// VkExtent3D           extent;
774 		1u,										// deUint32             mipLevels;
775 		1u,										// deUint32             arraySize;
776 		sampleCount,							// deUint32             samples;
777 		VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling        tiling;
778 		usage,									// VkImageUsageFlags    usage;
779 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode        sharingMode;
780 		1u,										// deUint32             queueFamilyCount;
781 		&m_queueFamilyIndex,					// const deUint32*      pQueueFamilyIndices;
782 		VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout        initialLayout;
783 	};
784 
785 	Move<VkImage> image = createImage(vk, m_device, &colorImageParams);
786 
787 	// Allocate and bind image memory
788 	de::MovePtr<Allocation> colorImageAlloc = m_allocator->allocate(getImageMemoryRequirements(vk, m_device, *image), MemoryRequirement::Any);
789 	VK_CHECK(vk.bindImageMemory(m_device, *image, colorImageAlloc->getMemory(), colorImageAlloc->getOffset()));
790 
791 	DE_ASSERT(pAlloc);
792 	*pAlloc = colorImageAlloc;
793 
794 	return image;
795 }
796 
createCustomDeviceWithTransferOnlyQueue(void)797 void TimestampTestInstance::createCustomDeviceWithTransferOnlyQueue(void)
798 {
799 	const InstanceInterface&	vki				= m_context.getInstanceInterface();
800 	const DeviceInterface&		vk				= m_context.getDeviceInterface();
801 	const VkPhysicalDevice		physicalDevice	= m_context.getPhysicalDevice();
802 
803 	m_queueFamilyIndex = findQueueFamilyIndexWithCaps(vki, physicalDevice, VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT);
804 
805 	const std::vector<VkQueueFamilyProperties>	queueFamilies = getPhysicalDeviceQueueFamilyProperties(vki, physicalDevice);
806 
807 	// This must be found, findQueueFamilyIndexWithCaps would have
808 	// thrown a NotSupported exception if the requested queue type did
809 	// not exist. Similarly, this was written with the assumption the
810 	// "alternative" queue would be different to the universal queue.
811 	DE_ASSERT(m_queueFamilyIndex < queueFamilies.size() && m_queueFamilyIndex != m_context.getUniversalQueueFamilyIndex());
812 	const float queuePriority = 1.0f;
813 	const VkDeviceQueueCreateInfo deviceQueueCreateInfos
814 	{
815 		VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,		// VkStructureType				sType;
816 		nullptr,										// const void*					pNext;
817 		(VkDeviceQueueCreateFlags)0u,					// VkDeviceQueueCreateFlags		flags;
818 		m_queueFamilyIndex,								// uint32_t						queueFamilyIndex;
819 		1u,												// uint32_t						queueCount;
820 		&queuePriority,									// const float*					pQueuePriorities;
821 	};
822 
823 	// Replicate default device extension list.
824 	const auto	extensionNames		= m_context.getDeviceCreationExtensions();
825 	auto queryResetFeatures			= m_context.getHostQueryResetFeatures();
826 	auto deviceFeatures2			= m_context.getDeviceFeatures2();
827 
828 	const void* pNext = &deviceFeatures2;
829 	if (m_context.getUsedApiVersion() < VK_API_VERSION_1_2) {
830 		queryResetFeatures.pNext = &deviceFeatures2;
831 		pNext = &queryResetFeatures;
832 	}
833 
834 #ifdef CTS_USES_VULKANSC
835 	VkDeviceObjectReservationCreateInfo memReservationInfo = m_context.getTestContext().getCommandLine().isSubProcess() ? m_context.getResourceInterface()->getStatMax() : resetDeviceObjectReservationCreateInfo();
836 	memReservationInfo.pNext = pNext;
837 	pNext = &memReservationInfo;
838 
839 	VkPipelineCacheCreateInfo			pcCI;
840 	std::vector<VkPipelinePoolSize>		poolSizes;
841 	if (m_context.getTestContext().getCommandLine().isSubProcess())
842 	{
843 		if (m_context.getResourceInterface()->getCacheDataSize() > 0)
844 		{
845 			pcCI =
846 			{
847 				VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO,			// VkStructureType				sType;
848 				DE_NULL,												// const void*					pNext;
849 				VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
850 					VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT,	// VkPipelineCacheCreateFlags	flags;
851 				m_context.getResourceInterface()->getCacheDataSize(),	// deUintptr					initialDataSize;
852 				m_context.getResourceInterface()->getCacheData()		// const void*					pInitialData;
853 			};
854 			memReservationInfo.pipelineCacheCreateInfoCount = 1;
855 			memReservationInfo.pPipelineCacheCreateInfos = &pcCI;
856 		}
857 		poolSizes = m_context.getResourceInterface()->getPipelinePoolSizes();
858 		if (!poolSizes.empty())
859 		{
860 			memReservationInfo.pipelinePoolSizeCount = deUint32(poolSizes.size());
861 			memReservationInfo.pPipelinePoolSizes = poolSizes.data();
862 		}
863 	}
864 #endif // CTS_USES_VULKANSC
865 
866 	const VkDeviceCreateInfo deviceCreateInfo
867 	{
868 		VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,			// VkStructureType					sType;
869 		pNext,											// const void*						pNext;
870 		(VkDeviceCreateFlags)0u,						// VkDeviceCreateFlags				flags;
871 		1u,												// uint32_t							queueCreateInfoCount;
872 		&deviceQueueCreateInfos,						// const VkDeviceQueueCreateInfo*	pQueueCreateInfos;
873 		0u,												// uint32_t							enabledLayerCount;
874 		DE_NULL,										// const char* const*				ppEnabledLayerNames;
875 		static_cast<uint32_t>(extensionNames.size()),	// uint32_t							enabledExtensionCount;
876 		extensionNames.data(),							// const char* const*				ppEnabledExtensionNames;
877 		DE_NULL,										// const VkPhysicalDeviceFeatures*	pEnabledFeatures;
878 	};
879 
880 	m_customDevice		= vkt::createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(), m_context.getPlatformInterface(), m_context.getInstance(), vki, physicalDevice, &deviceCreateInfo);
881 	m_customAllocator	= de::MovePtr<Allocator>(new SimpleAllocator(vk, *m_customDevice, getPhysicalDeviceMemoryProperties(vki, physicalDevice)));
882 
883 	m_device			= *m_customDevice;
884 	m_allocator			= &(*m_customAllocator);
885 }
886 
887 template <class T>
888 class CalibratedTimestampTest : public vkt::TestCase
889 {
890 public:
CalibratedTimestampTest(tcu::TestContext & testContext,const std::string & name)891 								CalibratedTimestampTest		(tcu::TestContext&		testContext,
892 															 const std::string&		name)
893 									: vkt::TestCase{testContext, name}
894 									{ }
895 
~CalibratedTimestampTest(void)896 	virtual						~CalibratedTimestampTest	(void) override { }
897 	virtual void				initPrograms				(SourceCollections&		programCollection) const override;
898 	virtual void				checkSupport				(Context&				context) const override;
899 	virtual vkt::TestInstance*	createInstance				(Context&				context) const override;
900 };
901 
902 class CalibratedTimestampTestInstance : public vkt::TestInstance
903 {
904 public:
905 							CalibratedTimestampTestInstance		(Context& context);
~CalibratedTimestampTestInstance(void)906 	virtual					~CalibratedTimestampTestInstance	(void) override { }
907 	virtual tcu::TestStatus iterate								(void) override;
908 	virtual tcu::TestStatus runTest								(void) = 0;
909 protected:
910 	struct CalibratedTimestamp
911 	{
CalibratedTimestampvkt::pipeline::__anonb6b85a350111::CalibratedTimestampTestInstance::CalibratedTimestamp912 		CalibratedTimestamp(deUint64 timestamp_, deUint64 deviation_) : timestamp{timestamp_}, deviation(deviation_) { }
CalibratedTimestampvkt::pipeline::__anonb6b85a350111::CalibratedTimestampTestInstance::CalibratedTimestamp913 		CalibratedTimestamp() : timestamp{}, deviation{} { }
914 		deUint64 timestamp;
915 		deUint64 deviation;
916 	};
917 
918 	std::vector<VkTimeDomainEXT>		getDomainSubset(const std::vector<VkTimeDomainEXT>& available, const std::vector<VkTimeDomainEXT>& interesting) const;
919 	std::string							domainName(VkTimeDomainEXT domain) const;
920 	deUint64							getHostNativeTimestamp(VkTimeDomainEXT hostDomain) const;
921 	deUint64							getHostNanoseconds(deUint64 hostTimestamp) const;
922 	deUint64							getDeviceNanoseconds(deUint64 devTicksDelta) const;
923 	std::vector<CalibratedTimestamp>	getCalibratedTimestamps(const std::vector<VkTimeDomainEXT>& domains);
924 	CalibratedTimestamp					getCalibratedTimestamp(VkTimeDomainEXT domain);
925 	void								appendQualityMessage(const std::string& message);
926 
927 	void								verifyDevTimestampMask(deUint64 value) const;
928 	deUint64							absDiffWithOverflow(deUint64 a, deUint64 b, deUint64 mask = std::numeric_limits<deUint64>::max()) const;
929 	deUint64							positiveDiffWithOverflow(deUint64 before, deUint64 after, deUint64 mask = std::numeric_limits<deUint64>::max()) const;
930 	bool								outOfRange(deUint64 begin, deUint64 middle, deUint64 end) const;
931 
932 	static constexpr deUint64		kBatchTimeLimitNanos		= 1000000000u;	// 1 sec.
933 	static constexpr deUint64		kDeviationErrorLimitNanos	=  100000000u;	// 100 ms.
934 	static constexpr deUint64		kDeviationWarningLimitNanos =   50000000u;	// 50 ms.
935 	static constexpr deUint64		kDefaultToleranceNanos		=  100000000u;	// 100 ms.
936 
937 #if (DE_OS == DE_OS_WIN32)
938 	// Preprocessor used to avoid warning about unused variable.
939 	static constexpr deUint64		kNanosecondsPerSecond		= 1000000000u;
940 #endif
941 	static constexpr deUint64		kNanosecondsPerMillisecond	=    1000000u;
942 
943 	std::string						m_qualityMessage;
944 	float							m_timestampPeriod;
945 	std::vector<VkTimeDomainEXT>	m_devDomains;
946 	std::vector<VkTimeDomainEXT>	m_hostDomains;
947 #if (DE_OS == DE_OS_WIN32)
948 	deUint64						m_frequency;
949 #endif
950 
951 	Move<VkCommandPool>				m_cmdPool;
952 	Move<VkCommandBuffer>			m_cmdBuffer;
953 	Move<VkQueryPool>				m_queryPool;
954 	deUint64						m_devTimestampMask;
955 };
956 
957 class CalibratedTimestampDevDomainTestInstance : public CalibratedTimestampTestInstance
958 {
959 public:
CalibratedTimestampDevDomainTestInstance(Context & context)960 							CalibratedTimestampDevDomainTestInstance	(Context& context)
961 								: CalibratedTimestampTestInstance{context}
962 								{ }
963 
~CalibratedTimestampDevDomainTestInstance(void)964 	virtual					~CalibratedTimestampDevDomainTestInstance	(void) { }
965 	virtual tcu::TestStatus runTest										(void) override;
966 };
967 
968 class CalibratedTimestampHostDomainTestInstance : public CalibratedTimestampTestInstance
969 {
970 public:
CalibratedTimestampHostDomainTestInstance(Context & context)971 							CalibratedTimestampHostDomainTestInstance	(Context& context)
972 								: CalibratedTimestampTestInstance{context}
973 								{ }
974 
~CalibratedTimestampHostDomainTestInstance(void)975 	virtual					~CalibratedTimestampHostDomainTestInstance	(void) { }
976 	virtual tcu::TestStatus runTest										(void) override;
977 };
978 
979 class CalibratedTimestampCalibrationTestInstance : public CalibratedTimestampTestInstance
980 {
981 public:
CalibratedTimestampCalibrationTestInstance(Context & context)982 							CalibratedTimestampCalibrationTestInstance	(Context& context)
983 								: CalibratedTimestampTestInstance{context}
984 								{ }
985 
~CalibratedTimestampCalibrationTestInstance(void)986 	virtual					~CalibratedTimestampCalibrationTestInstance	(void) { }
987 	virtual tcu::TestStatus runTest										(void) override;
988 };
989 
990 template <class T>
initPrograms(SourceCollections & programCollection) const991 void CalibratedTimestampTest<T>::initPrograms (SourceCollections& programCollection) const
992 {
993 	vkt::TestCase::initPrograms(programCollection);
994 }
995 
996 template <class T>
createInstance(Context & context) const997 vkt::TestInstance* CalibratedTimestampTest<T>::createInstance (Context& context) const
998 {
999 	return new T{context};
1000 }
1001 
1002 template <class T>
checkSupport(Context & context) const1003 void CalibratedTimestampTest<T>::checkSupport (Context& context) const
1004 {
1005 	context.requireDeviceFunctionality("VK_EXT_calibrated_timestamps");
1006 }
1007 
CalibratedTimestampTestInstance(Context & context)1008 CalibratedTimestampTestInstance::CalibratedTimestampTestInstance (Context& context)
1009 	: TestInstance{context}
1010 {
1011 #if (DE_OS == DE_OS_WIN32)
1012 	LARGE_INTEGER freq;
1013 	if (!QueryPerformanceFrequency(&freq))
1014 	{
1015 		throw tcu::ResourceError("Unable to get clock frequency with QueryPerformanceFrequency");
1016 	}
1017 	if (freq.QuadPart <= 0)
1018 	{
1019 		throw tcu::ResourceError("QueryPerformanceFrequency did not return a positive number");
1020 	}
1021 	m_frequency = static_cast<deUint64>(freq.QuadPart);
1022 #endif
1023 
1024 	const InstanceInterface&	vki					= context.getInstanceInterface();
1025 	const VkPhysicalDevice		physDevice			= context.getPhysicalDevice();
1026 	const deUint32				queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1027 
1028 	// Get timestamp mask.
1029 	m_devTimestampMask = checkTimestampsSupported(vki, physDevice, queueFamilyIndex);
1030 
1031 	// Get calibreatable time domains.
1032 	m_timestampPeriod = getPhysicalDeviceProperties(vki, physDevice).limits.timestampPeriod;
1033 
1034 	deUint32 domainCount;
1035 	VK_CHECK(vki.getPhysicalDeviceCalibrateableTimeDomainsEXT(physDevice, &domainCount, DE_NULL));
1036 	if (domainCount == 0)
1037 	{
1038 		throw tcu::NotSupportedError("No calibrateable time domains found");
1039 	}
1040 
1041 	std::vector<VkTimeDomainEXT> domains;
1042 	domains.resize(domainCount);
1043 	VK_CHECK(vki.getPhysicalDeviceCalibrateableTimeDomainsEXT(physDevice, &domainCount, domains.data()));
1044 
1045 	// Find the dev domain.
1046 	std::vector<VkTimeDomainEXT> preferredDevDomains;
1047 	preferredDevDomains.push_back(VK_TIME_DOMAIN_DEVICE_EXT);
1048 	m_devDomains = getDomainSubset(domains, preferredDevDomains);
1049 
1050 	// Find the host domain.
1051 	std::vector<VkTimeDomainEXT> preferredHostDomains;
1052 #if (DE_OS == DE_OS_WIN32)
1053 	preferredHostDomains.push_back(VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT);
1054 #else
1055 	preferredHostDomains.push_back(VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT);
1056 	preferredHostDomains.push_back(VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT);
1057 #endif
1058 	m_hostDomains = getDomainSubset(domains, preferredHostDomains);
1059 
1060 	// Initialize command buffers and queries.
1061 	const DeviceInterface&		vk				= context.getDeviceInterface();
1062 	const VkDevice				vkDevice		= context.getDevice();
1063 
1064 	const VkQueryPoolCreateInfo	queryPoolParams	=
1065 	{
1066 		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,	// VkStructureType               sType;
1067 		DE_NULL,									// const void*                   pNext;
1068 		0u,											// VkQueryPoolCreateFlags        flags;
1069 		VK_QUERY_TYPE_TIMESTAMP,					// VkQueryType                   queryType;
1070 		1u,											// deUint32                      entryCount;
1071 		0u,											// VkQueryPipelineStatisticFlags pipelineStatistics;
1072 	};
1073 
1074 	m_queryPool	= createQueryPool(vk, vkDevice, &queryPoolParams);
1075 	m_cmdPool	= createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
1076 	m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1077 
1078 	beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1079 	vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, 1u);
1080 	vk.cmdWriteTimestamp(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, *m_queryPool, 0u);
1081 	endCommandBuffer(vk, *m_cmdBuffer);
1082 }
1083 
getDomainSubset(const std::vector<VkTimeDomainEXT> & available,const std::vector<VkTimeDomainEXT> & interesting) const1084 std::vector<VkTimeDomainEXT> CalibratedTimestampTestInstance::getDomainSubset (const std::vector<VkTimeDomainEXT>& available, const std::vector<VkTimeDomainEXT>& interesting) const
1085 {
1086 	const std::set<VkTimeDomainEXT> availableSet	(begin(available),		end(available));
1087 	const std::set<VkTimeDomainEXT> interestingSet	(begin(interesting),	end(interesting));
1088 
1089 	std::vector<VkTimeDomainEXT> subset;
1090 	std::set_intersection(begin(availableSet), end(availableSet), begin(interestingSet), end(interestingSet), std::back_inserter(subset));
1091 	return subset;
1092 }
1093 
domainName(VkTimeDomainEXT domain) const1094 std::string CalibratedTimestampTestInstance::domainName(VkTimeDomainEXT domain) const
1095 {
1096 	switch (domain)
1097 	{
1098 	case VK_TIME_DOMAIN_DEVICE_EXT:						return "Device Domain";
1099 	case VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT:			return "Monotonic Clock";
1100 	case VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT:		return "Raw Monotonic Clock";
1101 	case VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT:	return "Query Performance Counter";
1102 	default:											DE_ASSERT(DE_FALSE); return "Unknown Time Domain";
1103 	}
1104 }
1105 
getHostNativeTimestamp(VkTimeDomainEXT hostDomain) const1106 deUint64 CalibratedTimestampTestInstance::getHostNativeTimestamp (VkTimeDomainEXT hostDomain) const
1107 {
1108 #if (DE_OS == DE_OS_WIN32)
1109 	DE_ASSERT(hostDomain == VK_TIME_DOMAIN_QUERY_PERFORMANCE_COUNTER_EXT);
1110 	LARGE_INTEGER result;
1111 	if (!QueryPerformanceCounter(&result))
1112 	{
1113 		throw tcu::ResourceError("Unable to obtain host native timestamp for Win32");
1114 	}
1115 	if (result.QuadPart < 0)
1116 	{
1117 		throw tcu::ResourceError("Host-native timestamp for Win32 less than zero");
1118 	}
1119 	return static_cast<deUint64>(result.QuadPart);
1120 #else
1121 	DE_ASSERT(hostDomain == VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT ||
1122 			  hostDomain == VK_TIME_DOMAIN_CLOCK_MONOTONIC_RAW_EXT);
1123 
1124 #if defined(CLOCK_MONOTONIC_RAW)
1125 	clockid_t id = ((hostDomain == VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT) ? CLOCK_MONOTONIC : CLOCK_MONOTONIC_RAW);
1126 #else
1127 	clockid_t id = CLOCK_MONOTONIC;
1128 #endif
1129 	struct timespec ts;
1130 	if (clock_gettime(id, &ts) != 0)
1131 	{
1132 		throw tcu::ResourceError("Unable to obtain host native timestamp for POSIX");
1133 	}
1134 	return (static_cast<deUint64>(ts.tv_sec) * 1000000000ULL + ts.tv_nsec);
1135 #endif
1136 }
1137 
getHostNanoseconds(deUint64 hostTimestamp) const1138 deUint64 CalibratedTimestampTestInstance::getHostNanoseconds (deUint64 hostTimestamp) const
1139 {
1140 #if (DE_OS == DE_OS_WIN32)
1141 	deUint64	secs	= hostTimestamp / m_frequency;
1142 	deUint64	nanos	= ((hostTimestamp % m_frequency) * kNanosecondsPerSecond) / m_frequency;
1143 
1144 	return ((secs * kNanosecondsPerSecond) + nanos);
1145 #else
1146 	return hostTimestamp;
1147 #endif
1148 }
1149 
1150 // This method will be used when devTicksDelta is (supposedly) a small amount of ticks between two events. We will check
1151 // devTicksDelta is reasonably small for the calculation below to succeed without losing precision.
getDeviceNanoseconds(deUint64 devTicksDelta) const1152 deUint64 CalibratedTimestampTestInstance::getDeviceNanoseconds (deUint64 devTicksDelta) const
1153 {
1154 	if (devTicksDelta > static_cast<deUint64>(std::numeric_limits<deUint32>::max()))
1155 	{
1156 		std::ostringstream msg;
1157 		msg << "Number of device ticks too big for conversion to nanoseconds: " << devTicksDelta;
1158 		throw tcu::InternalError(msg.str());
1159 	}
1160 	return static_cast<deUint64>(static_cast<double>(devTicksDelta) * m_timestampPeriod);
1161 }
1162 
iterate(void)1163 tcu::TestStatus CalibratedTimestampTestInstance::iterate (void)
1164 {
1165 	// Notes:
1166 	//	1) Clocks may overflow.
1167 	//	2) Because m_timestampPeriod is a floating point value, there may be less than one nano per tick.
1168 
1169 	const tcu::TestStatus result = runTest();
1170 	if (result.getCode() != QP_TEST_RESULT_PASS)
1171 		return result;
1172 
1173 	if (!m_qualityMessage.empty())
1174 	{
1175 		const std::string msg = "Warnings found: " + m_qualityMessage;
1176 		return tcu::TestStatus(QP_TEST_RESULT_QUALITY_WARNING, msg);
1177 	}
1178 	return tcu::TestStatus::pass("Pass");
1179 }
1180 
1181 // Verify all invalid timestamp bits are zero.
verifyDevTimestampMask(deUint64 value) const1182 void CalibratedTimestampTestInstance::verifyDevTimestampMask (deUint64 value) const
1183 {
1184 	checkTimestampBits(value, m_devTimestampMask);
1185 }
1186 
1187 // Absolute difference between two timestamps A and B taking overflow into account. Pick the smallest difference between the two
1188 // possibilities. We don't know beforehand if B > A or vice versa. Take the valid bit mask into account.
absDiffWithOverflow(deUint64 a,deUint64 b,deUint64 mask) const1189 deUint64 CalibratedTimestampTestInstance::absDiffWithOverflow (deUint64 a, deUint64 b, deUint64 mask) const
1190 {
1191 	//	<---------+ range +-------->
1192 	//
1193 	//	+--------------------------+
1194 	//	|         deUint64         |
1195 	//	+------^-----------^-------+
1196 	//	       +           +
1197 	//	       a           b
1198 	//	       +----------->
1199 	//	       ccccccccccccc
1200 	//	------>             +-------
1201 	//	ddddddd             dddddddd
1202 
1203 	DE_ASSERT(a <= mask);
1204 	DE_ASSERT(b <= mask);
1205 
1206 	const deUint64 c = ((a >= b) ? (a - b) : (b - a));
1207 
1208 	if (c == 0u)
1209 		return c;
1210 
1211 	const deUint64 d = (mask - c) + 1;
1212 
1213 	return ((c < d) ? c : d);
1214 }
1215 
1216 // Positive difference between both marks, advancing from before to after, taking overflow and the valid bit mask into account.
positiveDiffWithOverflow(deUint64 before,deUint64 after,deUint64 mask) const1217 deUint64 CalibratedTimestampTestInstance::positiveDiffWithOverflow (deUint64 before, deUint64 after, deUint64 mask) const
1218 {
1219 	DE_ASSERT(before <= mask);
1220 	DE_ASSERT(after  <= mask);
1221 
1222 	return ((before <= after) ? (after - before) : ((mask - (before - after)) + 1));
1223 }
1224 
1225 // Return true if middle is not between begin and end, taking overflow into account.
outOfRange(deUint64 begin,deUint64 middle,deUint64 end) const1226 bool CalibratedTimestampTestInstance::outOfRange (deUint64 begin, deUint64 middle, deUint64 end) const
1227 {
1228 	return (((begin <= end) && (middle < begin || middle > end	)) ||
1229 			((begin >  end) && (middle > end   && middle < begin)));
1230 }
1231 
getCalibratedTimestamps(const std::vector<VkTimeDomainEXT> & domains)1232 std::vector<CalibratedTimestampTestInstance::CalibratedTimestamp> CalibratedTimestampTestInstance::getCalibratedTimestamps (const std::vector<VkTimeDomainEXT>& domains)
1233 {
1234 	std::vector<VkCalibratedTimestampInfoEXT> infos;
1235 
1236 	for (auto domain : domains)
1237 	{
1238 		VkCalibratedTimestampInfoEXT info;
1239 		info.sType = getStructureType<VkCalibratedTimestampInfoEXT>();
1240 		info.pNext = DE_NULL;
1241 		info.timeDomain = domain;
1242 		infos.push_back(info);
1243 	}
1244 
1245 	std::vector<deUint64> timestamps(domains.size());
1246 	deUint64			  deviation;
1247 
1248 	const DeviceInterface&      vk          = m_context.getDeviceInterface();
1249 	const VkDevice              vkDevice    = m_context.getDevice();
1250 
1251 	VK_CHECK(vk.getCalibratedTimestampsEXT(vkDevice, static_cast<deUint32>(domains.size()), infos.data(), timestamps.data(), &deviation));
1252 
1253 	if (deviation > kDeviationErrorLimitNanos)
1254 	{
1255 		throw tcu::InternalError("Calibrated maximum deviation too big");
1256 	}
1257 	else if (deviation > kDeviationWarningLimitNanos)
1258 	{
1259 		appendQualityMessage("Calibrated maximum deviation beyond desirable limits");
1260 	}
1261 	else if (deviation == 0 && domains.size() > 1)
1262 	{
1263 		appendQualityMessage("Calibrated maximum deviation reported as zero");
1264 	}
1265 
1266 	// Pack results.
1267 	std::vector<CalibratedTimestamp> results;
1268 
1269 	for (size_t i = 0; i < domains.size(); ++i)
1270 	{
1271 		if (domains[i] == VK_TIME_DOMAIN_DEVICE_EXT)
1272 			verifyDevTimestampMask(timestamps[i]);
1273 		results.emplace_back(timestamps[i], deviation);
1274 	}
1275 
1276 	return results;
1277 }
1278 
getCalibratedTimestamp(VkTimeDomainEXT domain)1279 CalibratedTimestampTestInstance::CalibratedTimestamp CalibratedTimestampTestInstance::getCalibratedTimestamp (VkTimeDomainEXT domain)
1280 {
1281 	// Single domain, single result.
1282 	return getCalibratedTimestamps(std::vector<VkTimeDomainEXT>(1, domain))[0];
1283 }
1284 
appendQualityMessage(const std::string & message)1285 void CalibratedTimestampTestInstance::appendQualityMessage (const std::string& message)
1286 {
1287 	if (!m_qualityMessage.empty())
1288 		m_qualityMessage += "; ";
1289 
1290 	m_qualityMessage += message;
1291 }
1292 
1293 // Test device domain makes sense and is consistent with vkCmdWriteTimestamp().
runTest(void)1294 tcu::TestStatus CalibratedTimestampDevDomainTestInstance::runTest (void)
1295 {
1296 	if (m_devDomains.empty())
1297 		throw tcu::NotSupportedError("No suitable device time domains found");
1298 
1299 	const DeviceInterface&      vk          = m_context.getDeviceInterface();
1300 	const VkDevice              vkDevice    = m_context.getDevice();
1301 	const VkQueue               queue       = m_context.getUniversalQueue();
1302 
1303 	for (const auto devDomain : m_devDomains)
1304 	{
1305 		const CalibratedTimestamp	before		= getCalibratedTimestamp(devDomain);
1306 		submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
1307 		const CalibratedTimestamp	after		= getCalibratedTimestamp(devDomain);
1308 		const deUint64				diffNanos	= getDeviceNanoseconds(positiveDiffWithOverflow(before.timestamp, after.timestamp, m_devTimestampMask));
1309 		deUint64					written;
1310 		VK_CHECK(vk.getQueryPoolResults(vkDevice, *m_queryPool, 0u, 1u, sizeof(written), &written, sizeof(written), (VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT)));
1311 		verifyDevTimestampMask(written);
1312 
1313 		if (diffNanos > kBatchTimeLimitNanos)
1314 		{
1315 			return tcu::TestStatus::fail(domainName(devDomain) + ": Batch of work took too long to execute");
1316 		}
1317 
1318 		if (outOfRange(before.timestamp, written, after.timestamp))
1319 		{
1320 			return tcu::TestStatus::fail(domainName(devDomain) + ": vkCmdWriteTimestamp() inconsistent with vkGetCalibratedTimestampsEXT()");
1321 		}
1322 	}
1323 
1324 	return tcu::TestStatus::pass("Pass");
1325 }
1326 
1327 // Test host domain makes sense and is consistent with native host values.
runTest(void)1328 tcu::TestStatus CalibratedTimestampHostDomainTestInstance::runTest (void)
1329 {
1330 	if (m_hostDomains.empty())
1331 		throw tcu::NotSupportedError("No suitable host time domains found");
1332 
1333 	for (const auto hostDomain : m_hostDomains)
1334 	{
1335 		const deUint64				before		= getHostNativeTimestamp(hostDomain);
1336 		const CalibratedTimestamp	vkTS		= getCalibratedTimestamp(hostDomain);
1337 		const deUint64				after		= getHostNativeTimestamp(hostDomain);
1338 		const deUint64				diffNanos	= getHostNanoseconds(positiveDiffWithOverflow(before, after));
1339 
1340 		if (diffNanos > kBatchTimeLimitNanos)
1341 		{
1342 			return tcu::TestStatus::fail(domainName(hostDomain) + ": Querying host domain took too long to execute");
1343 		}
1344 
1345 		if (outOfRange(before, vkTS.timestamp, after))
1346 		{
1347 			return tcu::TestStatus::fail(domainName(hostDomain) + ": vkGetCalibratedTimestampsEXT() inconsistent with native host API");
1348 		}
1349 	}
1350 
1351 	return tcu::TestStatus::pass("Pass");
1352 }
1353 
1354 // Verify predictable timestamps and calibration possible.
runTest(void)1355 tcu::TestStatus CalibratedTimestampCalibrationTestInstance::runTest (void)
1356 {
1357 	if (m_devDomains.empty())
1358 		throw tcu::NotSupportedError("No suitable device time domains found");
1359 	if (m_hostDomains.empty())
1360 		throw tcu::NotSupportedError("No suitable host time domains found");
1361 
1362 	// Sleep time.
1363 	constexpr deUint32	kSleepMilliseconds	= 200;
1364 	constexpr deUint32	kSleepNanoseconds	= kSleepMilliseconds * kNanosecondsPerMillisecond;
1365 
1366 	for (const auto devDomain	: m_devDomains)
1367 	for (const auto hostDomain	: m_hostDomains)
1368 	{
1369 		std::vector<VkTimeDomainEXT>	domains;
1370 		domains.push_back(devDomain);	// Device results at index 0.
1371 		domains.push_back(hostDomain);	// Host results at index 1.
1372 
1373 		// Measure time.
1374 		const std::vector<CalibratedTimestamp> before	= getCalibratedTimestamps(domains);
1375 		std::this_thread::sleep_for(std::chrono::nanoseconds(kSleepNanoseconds));
1376 		const std::vector<CalibratedTimestamp> after	= getCalibratedTimestamps(domains);
1377 
1378 		// Check device timestamp is as expected.
1379 		const deUint64 devBeforeTicks	= before[0].timestamp;
1380 		const deUint64 devAfterTicks	= after[0].timestamp;
1381 		const deUint64 devExpectedTicks	= ((devBeforeTicks + static_cast<deUint64>(static_cast<double>(kSleepNanoseconds) / m_timestampPeriod)) & m_devTimestampMask);
1382 		const deUint64 devDiffNanos		= getDeviceNanoseconds(absDiffWithOverflow(devAfterTicks, devExpectedTicks, m_devTimestampMask));
1383 		const deUint64 maxDevDiffNanos	= std::max({ kDefaultToleranceNanos, before[0].deviation + after[0].deviation });
1384 
1385 		if (devDiffNanos > maxDevDiffNanos)
1386 		{
1387 			std::ostringstream msg;
1388 			msg << "[" << domainName(devDomain) << "] Device expected timestamp differs " << devDiffNanos << " nanoseconds (expect value <= " << maxDevDiffNanos << ")";
1389 			return tcu::TestStatus::fail(msg.str());
1390 		}
1391 
1392 		// Check host timestamp is as expected.
1393 		const deUint64 hostBefore		= getHostNanoseconds(before[1].timestamp);
1394 		const deUint64 hostAfter		= getHostNanoseconds(after[1].timestamp);
1395 		const deUint64 hostExpected		= hostBefore + kSleepNanoseconds;
1396 		const deUint64 hostDiff			= absDiffWithOverflow(hostAfter, hostExpected);
1397 		const deUint64 maxHostDiff		= std::max({ kDefaultToleranceNanos, before[1].deviation + after[1].deviation });
1398 
1399 		if (hostDiff > maxHostDiff)
1400 		{
1401 			std::ostringstream msg;
1402 			msg << "[" << domainName(hostDomain) << "] Host expected timestamp differs " << hostDiff << " nanoseconds (expected value <= " << maxHostDiff << ")";
1403 			return tcu::TestStatus::fail(msg.str());
1404 		}
1405 	}
1406 
1407 	return tcu::TestStatus::pass("Pass");
1408 }
1409 
1410 class BasicGraphicsTest : public TimestampTest
1411 {
1412 public:
BasicGraphicsTest(tcu::TestContext & testContext,const std::string & name,const TimestampTestParam * param)1413 							BasicGraphicsTest	(tcu::TestContext&			testContext,
1414 												 const std::string&			name,
1415 												 const TimestampTestParam*	param)
1416 							: TimestampTest (testContext, name, param)
1417 { }
~BasicGraphicsTest(void)1418 	virtual					~BasicGraphicsTest	(void) { }
1419 	virtual void			initPrograms		(SourceCollections& programCollection) const;
1420 	virtual TestInstance*	createInstance		(Context& context) const;
1421 };
1422 
1423 class BasicGraphicsTestInstance : public TimestampTestInstance
1424 {
1425 public:
1426 	enum
1427 	{
1428 		VK_MAX_SHADER_STAGES = 6,
1429 	};
1430 					BasicGraphicsTestInstance	(Context&						context,
1431 												 const PipelineConstructionType	pipelineConstructionType,
1432 												 const StageFlagVector			stages,
1433 												 const bool						inRenderPass,
1434 												 const bool						hostQueryReset,
1435 												 const VkQueryResultFlags		queryResultFlags);
1436 
1437 	virtual			~BasicGraphicsTestInstance	(void);
1438 protected:
1439 	virtual void	buildPipeline				(void);
1440 	virtual void	configCommandBuffer			(void);
1441 	virtual void	buildVertexBuffer			(void);
1442 	virtual void	buildRenderPass				(VkFormat	colorFormat,
1443 												 VkFormat	depthFormat);
1444 
1445 	virtual void	buildFrameBuffer			(tcu::UVec2	renderSize,
1446 												 VkFormat	colorFormat,
1447 												 VkFormat	depthFormat);
1448 
1449 protected:
1450 	const PipelineConstructionType	m_pipelineConstructionType;
1451 	const tcu::UVec2				m_renderSize;
1452 	const VkFormat					m_colorFormat;
1453 	const VkFormat					m_depthFormat;
1454 
1455 	Move<VkImage>					m_colorImage;
1456 	de::MovePtr<Allocation>			m_colorImageAlloc;
1457 	Move<VkImage>					m_depthImage;
1458 	de::MovePtr<Allocation>			m_depthImageAlloc;
1459 	Move<VkImageView>				m_colorAttachmentView;
1460 	Move<VkImageView>				m_depthAttachmentView;
1461 	RenderPassWrapper				m_renderPass;
1462 	Move<VkFramebuffer>				m_framebuffer;
1463 	VkImageMemoryBarrier			m_imageLayoutBarriers[2];
1464 
1465 	de::MovePtr<Allocation>			m_vertexBufferAlloc;
1466 	Move<VkBuffer>					m_vertexBuffer;
1467 	std::vector<Vertex4RGBA>		m_vertices;
1468 
1469 	PipelineLayoutWrapper			m_pipelineLayout;
1470 	GraphicsPipelineWrapper			m_graphicsPipeline;
1471 };
1472 
initPrograms(SourceCollections & programCollection) const1473 void BasicGraphicsTest::initPrograms (SourceCollections& programCollection) const
1474 {
1475 	programCollection.glslSources.add("color_vert") << glu::VertexSource(
1476 		"#version 310 es\n"
1477 		"layout(location = 0) in vec4 position;\n"
1478 		"layout(location = 1) in vec4 color;\n"
1479 		"layout(location = 0) out highp vec4 vtxColor;\n"
1480 		"void main (void)\n"
1481 		"{\n"
1482 		"  gl_Position = position;\n"
1483 		"  vtxColor = color;\n"
1484 		"}\n");
1485 
1486 	programCollection.glslSources.add("color_frag") << glu::FragmentSource(
1487 		"#version 310 es\n"
1488 		"layout(location = 0) in highp vec4 vtxColor;\n"
1489 		"layout(location = 0) out highp vec4 fragColor;\n"
1490 		"void main (void)\n"
1491 		"{\n"
1492 		"  fragColor = vtxColor;\n"
1493 		"}\n");
1494 }
1495 
createInstance(Context & context) const1496 TestInstance* BasicGraphicsTest::createInstance (Context& context) const
1497 {
1498 	return new BasicGraphicsTestInstance(context, m_pipelineConstructionType, m_stages, m_inRenderPass, m_hostQueryReset, m_queryResultFlags);
1499 }
1500 
buildVertexBuffer(void)1501 void BasicGraphicsTestInstance::buildVertexBuffer (void)
1502 {
1503 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
1504 
1505 	// Create vertex buffer
1506 	{
1507 		m_vertexBuffer	= createBufferAndBindMemory(1024u, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, &m_vertexBufferAlloc);
1508 		m_vertices		= createOverlappingQuads();
1509 
1510 		// Load vertices into vertex buffer
1511 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
1512 		flushAlloc(vk, m_device, *m_vertexBufferAlloc);
1513 	}
1514 }
1515 
buildRenderPass(VkFormat colorFormat,VkFormat depthFormat)1516 void BasicGraphicsTestInstance::buildRenderPass (VkFormat colorFormat, VkFormat depthFormat)
1517 {
1518 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
1519 
1520 	// Create render pass
1521 	m_renderPass = RenderPassWrapper(m_pipelineConstructionType, vk, m_device, colorFormat, depthFormat);
1522 }
1523 
buildFrameBuffer(tcu::UVec2 renderSize,VkFormat colorFormat,VkFormat depthFormat)1524 void BasicGraphicsTestInstance::buildFrameBuffer (tcu::UVec2 renderSize, VkFormat colorFormat, VkFormat depthFormat)
1525 {
1526 	const DeviceInterface&		vk						= m_context.getDeviceInterface();
1527 	const VkComponentMapping	ComponentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
1528 
1529 	// Create color image
1530 	{
1531 		m_colorImage = createImage2DAndBindMemory(colorFormat,
1532 												  renderSize.x(),
1533 												  renderSize.y(),
1534 												  VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
1535 												  VK_SAMPLE_COUNT_1_BIT,
1536 												  &m_colorImageAlloc);
1537 	}
1538 
1539 	// Create depth image
1540 	{
1541 		m_depthImage = createImage2DAndBindMemory(depthFormat,
1542 												  renderSize.x(),
1543 												  renderSize.y(),
1544 												  VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
1545 												  VK_SAMPLE_COUNT_1_BIT,
1546 												  &m_depthImageAlloc);
1547 	}
1548 
1549 	// Set up image layout transition barriers
1550 	{
1551 		const VkImageMemoryBarrier colorImageBarrier =
1552 		{
1553 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
1554 			DE_NULL,											// const void*				pNext;
1555 			0u,													// VkAccessFlags			srcAccessMask;
1556 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,				// VkAccessFlags			dstAccessMask;
1557 			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
1558 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout			newLayout;
1559 			VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
1560 			VK_QUEUE_FAMILY_IGNORED,							// deUint32					dstQueueFamilyIndex;
1561 			*m_colorImage,										// VkImage					image;
1562 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },		// VkImageSubresourceRange	subresourceRange;
1563 		};
1564 		const VkImageMemoryBarrier depthImageBarrier =
1565 		{
1566 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
1567 			DE_NULL,											// const void*				pNext;
1568 			0u,													// VkAccessFlags			srcAccessMask;
1569 			VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			dstAccessMask;
1570 			VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
1571 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout			newLayout;
1572 			VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
1573 			VK_QUEUE_FAMILY_IGNORED,							// deUint32					dstQueueFamilyIndex;
1574 			*m_depthImage,										// VkImage					image;
1575 			{ VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u },		// VkImageSubresourceRange	subresourceRange;
1576 		};
1577 
1578 		m_imageLayoutBarriers[0] = colorImageBarrier;
1579 		m_imageLayoutBarriers[1] = depthImageBarrier;
1580 	}
1581 
1582 	// Create color attachment view
1583 	{
1584 		const VkImageViewCreateInfo colorAttachmentViewParams =
1585 		{
1586 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType          sType;
1587 			DE_NULL,										// const void*              pNext;
1588 			0u,												// VkImageViewCreateFlags   flags;
1589 			*m_colorImage,									// VkImage                  image;
1590 			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType          viewType;
1591 			colorFormat,									// VkFormat                 format;
1592 			ComponentMappingRGBA,							// VkComponentMapping       components;
1593 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange  subresourceRange;
1594 		};
1595 
1596 		m_colorAttachmentView = createImageView(vk, m_device, &colorAttachmentViewParams);
1597 	}
1598 
1599 	// Create depth attachment view
1600 	{
1601 		const VkImageViewCreateInfo depthAttachmentViewParams =
1602 		{
1603 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,		// VkStructureType          sType;
1604 			DE_NULL,										// const void*              pNext;
1605 			0u,												// VkImageViewCreateFlags   flags;
1606 			*m_depthImage,									// VkImage                  image;
1607 			VK_IMAGE_VIEW_TYPE_2D,							// VkImageViewType          viewType;
1608 			depthFormat,									// VkFormat                 format;
1609 			ComponentMappingRGBA,							// VkComponentMapping       components;
1610 			{ VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u },	// VkImageSubresourceRange  subresourceRange;
1611 		};
1612 
1613 		m_depthAttachmentView = createImageView(vk, m_device, &depthAttachmentViewParams);
1614 	}
1615 
1616 	// Create framebuffer
1617 	{
1618 		const std::vector<VkImage> images =
1619 		{
1620 			*m_colorImage,
1621 			*m_depthImage,
1622 		};
1623 		const VkImageView attachmentBindInfos[2] =
1624 		{
1625 			*m_colorAttachmentView,
1626 			*m_depthAttachmentView,
1627 		};
1628 
1629 		const VkFramebufferCreateInfo framebufferParams =
1630 		{
1631 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType              sType;
1632 			DE_NULL,									// const void*                  pNext;
1633 			0u,											// VkFramebufferCreateFlags     flags;
1634 			*m_renderPass,								// VkRenderPass                 renderPass;
1635 			2u,											// deUint32                     attachmentCount;
1636 			attachmentBindInfos,						// const VkImageView*           pAttachments;
1637 			(deUint32)renderSize.x(),					// deUint32                     width;
1638 			(deUint32)renderSize.y(),					// deUint32                     height;
1639 			1u,											// deUint32                     layers;
1640 		};
1641 
1642 		m_renderPass.createFramebuffer(vk, m_device, &framebufferParams, images);
1643 	}
1644 
1645 }
1646 
BasicGraphicsTestInstance(Context & context,const PipelineConstructionType pipelineConstructionType,const StageFlagVector stages,const bool inRenderPass,const bool hostQueryReset,const VkQueryResultFlags queryResultFlags)1647 BasicGraphicsTestInstance::BasicGraphicsTestInstance (Context&							context,
1648 													  const PipelineConstructionType	pipelineConstructionType,
1649 													  const StageFlagVector				stages,
1650 													  const bool						inRenderPass,
1651 													  const bool						hostQueryReset,
1652 													  const VkQueryResultFlags			queryResultFlags)
1653 													  : TimestampTestInstance		(context, stages, inRenderPass, hostQueryReset, false, queryResultFlags)
1654 													  , m_pipelineConstructionType	(pipelineConstructionType)
1655 													  , m_renderSize				(32, 32)
1656 													  , m_colorFormat				(VK_FORMAT_R8G8B8A8_UNORM)
1657 													  , m_depthFormat				(VK_FORMAT_D16_UNORM)
1658 													  , m_graphicsPipeline			(context.getInstanceInterface(), context.getDeviceInterface(), context.getPhysicalDevice(), context.getDevice(), context.getDeviceExtensions(), pipelineConstructionType)
1659 {
1660 	buildVertexBuffer();
1661 
1662 	buildRenderPass(m_colorFormat, m_depthFormat);
1663 
1664 	buildFrameBuffer(m_renderSize, m_colorFormat, m_depthFormat);
1665 
1666 	// Create pipeline layout
1667 	const DeviceInterface&				vk						= m_context.getDeviceInterface();
1668 	const VkPipelineLayoutCreateInfo	pipelineLayoutParams	= initVulkanStructure();
1669 	m_pipelineLayout = PipelineLayoutWrapper(pipelineConstructionType, vk, m_device, &pipelineLayoutParams);
1670 }
1671 
~BasicGraphicsTestInstance(void)1672 BasicGraphicsTestInstance::~BasicGraphicsTestInstance (void)
1673 {
1674 }
1675 
1676 static const VkVertexInputBindingDescription defaultVertexInputBindingDescription
1677 {
1678 	0u,																// deUint32				binding;
1679 	sizeof(Vertex4RGBA),											// deUint32				strideInBytes;
1680 	VK_VERTEX_INPUT_RATE_VERTEX,									// VkVertexInputRate	inputRate;
1681 };
1682 
1683 static const VkVertexInputAttributeDescription defaultVertexInputAttributeDescriptions[2]
1684 {
1685 	{
1686 		0u,															// deUint32				location;
1687 		0u,															// deUint32				binding;
1688 		VK_FORMAT_R32G32B32A32_SFLOAT,								// VkFormat				format;
1689 		0u															// deUint32				offsetInBytes;
1690 	},
1691 	{
1692 		1u,															// deUint32				location;
1693 		0u,															// deUint32				binding;
1694 		VK_FORMAT_R32G32B32A32_SFLOAT,								// VkFormat				format;
1695 		DE_OFFSET_OF(Vertex4RGBA, color),							// deUint32				offsetInBytes;
1696 	}
1697 };
1698 
1699 static const VkPipelineVertexInputStateCreateInfo defaultVertexInputStateParams
1700 {
1701 	VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType								sType;
1702 	DE_NULL,														// const void*									pNext;
1703 	0u,																// VkPipelineVertexInputStateCreateFlags		flags;
1704 	1u,																// deUint32										vertexBindingDescriptionCount;
1705 	&defaultVertexInputBindingDescription,							// const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
1706 	2u,																// deUint32										vertexAttributeDescriptionCount;
1707 	defaultVertexInputAttributeDescriptions,						// const VkVertexInputAttributeDescription*		pVertexAttributeDescriptions;
1708 };
1709 
1710 static const VkPipelineDepthStencilStateCreateInfo defaultDepthStencilStateParams
1711 {
1712 	VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,		// VkStructureType								sType;
1713 	DE_NULL,														// const void*									pNext;
1714 	0u,																// VkPipelineDepthStencilStateCreateFlags		flags;
1715 	VK_TRUE,														// VkBool32										depthTestEnable;
1716 	VK_TRUE,														// VkBool32										depthWriteEnable;
1717 	VK_COMPARE_OP_LESS_OR_EQUAL,									// VkCompareOp									depthCompareOp;
1718 	VK_FALSE,														// VkBool32										depthBoundsTestEnable;
1719 	VK_FALSE,														// VkBool32										stencilTestEnable;
1720 	{																// VkStencilOpState								front;
1721 		VK_STENCIL_OP_KEEP,												// VkStencilOp								failOp
1722 		VK_STENCIL_OP_KEEP,												// VkStencilOp								passOp
1723 		VK_STENCIL_OP_KEEP,												// VkStencilOp								depthFailOp
1724 		VK_COMPARE_OP_NEVER,											// VkCompareOp								compareOp
1725 		0u,																// deUint32									compareMask
1726 		0u,																// deUint32									writeMask
1727 		0u																// deUint32									reference
1728 	},
1729 	{																// VkStencilOpState								back;
1730 		VK_STENCIL_OP_KEEP,												// VkStencilOp								failOp
1731 		VK_STENCIL_OP_KEEP,												// VkStencilOp								passOp
1732 		VK_STENCIL_OP_KEEP,												// VkStencilOp								depthFailOp
1733 		VK_COMPARE_OP_NEVER,											// VkCompareOp								compareOp
1734 		0u,																// deUint32									compareMask
1735 		0u,																// deUint32									writeMask
1736 		0u																// deUint32									reference
1737 	},
1738 	0.0f,															// float										minDepthBounds;
1739 	1.0f,															// float										maxDepthBounds;
1740 };
1741 
buildPipeline(void)1742 void BasicGraphicsTestInstance::buildPipeline(void)
1743 {
1744 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
1745 
1746 	auto vertexShaderModule		= ShaderWrapper(vk, m_device, m_context.getBinaryCollection().get("color_vert"), 0);
1747 	auto fragmentShaderModule	= ShaderWrapper(vk, m_device, m_context.getBinaryCollection().get("color_frag"), 0);
1748 
1749 	const std::vector<VkViewport>	viewports	{ makeViewport(m_renderSize) };
1750 	const std::vector<VkRect2D>		scissors	{ makeRect2D(m_renderSize) };
1751 
1752 	// Create pipeline
1753 	m_graphicsPipeline.setDefaultRasterizationState()
1754 					  .setDefaultColorBlendState()
1755 					  .setDefaultMultisampleState()
1756 					  .setupVertexInputState(&defaultVertexInputStateParams)
1757 					  .setupPreRasterizationShaderState(viewports,
1758 														scissors,
1759 														m_pipelineLayout,
1760 														*m_renderPass,
1761 														0u,
1762 														vertexShaderModule)
1763 					  .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, fragmentShaderModule, &defaultDepthStencilStateParams)
1764 					  .setupFragmentOutputState(*m_renderPass)
1765 					  .setMonolithicPipelineLayout(m_pipelineLayout)
1766 					  .buildPipeline();
1767 }
1768 
configCommandBuffer(void)1769 void BasicGraphicsTestInstance::configCommandBuffer (void)
1770 {
1771 	const DeviceInterface&		vk							= m_context.getDeviceInterface();
1772 
1773 	const VkClearValue			attachmentClearValues[2]	=
1774 	{
1775 		defaultClearValue(m_colorFormat),
1776 		defaultClearValue(m_depthFormat),
1777 	};
1778 
1779 	beginCommandBuffer(vk, *m_cmdBuffer, 0u);
1780 
1781 	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, (VkDependencyFlags)0,
1782 		0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(m_imageLayoutBarriers), m_imageLayoutBarriers);
1783 
1784 	if (!m_hostQueryReset)
1785 		vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
1786 
1787 	m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), 2u, attachmentClearValues);
1788 
1789 	m_graphicsPipeline.bind(*m_cmdBuffer);
1790 	VkDeviceSize offsets = 0u;
1791 	vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &offsets);
1792 	vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1u, 0u, 0u);
1793 
1794 	if(m_inRenderPass)
1795 	{
1796 	  deUint32 timestampEntry = 0u;
1797 
1798 	  for (StageFlagVector::const_iterator it = m_stages.begin(); it != m_stages.end(); it++)
1799 	  {
1800 		  vk.cmdWriteTimestamp(*m_cmdBuffer, *it, *m_queryPool, timestampEntry++);
1801 	  }
1802 	}
1803 
1804 	m_renderPass.end(vk, *m_cmdBuffer);
1805 
1806 	if(!m_inRenderPass)
1807 	{
1808 	  deUint32 timestampEntry = 0u;
1809 
1810 	  for (StageFlagVector::const_iterator it = m_stages.begin(); it != m_stages.end(); it++)
1811 	  {
1812 		  vk.cmdWriteTimestamp(*m_cmdBuffer, *it, *m_queryPool, timestampEntry++);
1813 	  }
1814 	}
1815 
1816 	endCommandBuffer(vk, *m_cmdBuffer);
1817 }
1818 
1819 class AdvGraphicsTest : public BasicGraphicsTest
1820 {
1821 public:
AdvGraphicsTest(tcu::TestContext & testContext,const std::string & name,const TimestampTestParam * param)1822 						  AdvGraphicsTest	(tcu::TestContext&			testContext,
1823 											 const std::string&			name,
1824 											 const TimestampTestParam*	param)
1825 							  : BasicGraphicsTest(testContext, name, param)
1826 							  { }
1827 
~AdvGraphicsTest(void)1828 	virtual              ~AdvGraphicsTest (void) { }
1829 	virtual void         initPrograms     (SourceCollections& programCollection) const;
1830 	virtual TestInstance*createInstance   (Context& context) const;
1831 };
1832 
1833 class AdvGraphicsTestInstance : public BasicGraphicsTestInstance
1834 {
1835 public:
1836 				 AdvGraphicsTestInstance	(Context&							context,
1837 											 const PipelineConstructionType		pipelineConstructionType,
1838 											 const StageFlagVector				stages,
1839 											 const bool							inRenderPass,
1840 											 const bool							hostQueryReset,
1841 											 const VkQueryResultFlags			queryResultFlags);
1842 
1843 	virtual      ~AdvGraphicsTestInstance	(void);
1844 	virtual void buildPipeline				(void);
1845 	virtual void configCommandBuffer		(void);
1846 
1847 protected:
1848 	virtual void featureSupportCheck		(void);
1849 
1850 protected:
1851 	VkPhysicalDeviceFeatures	m_features;
1852 	deUint32					m_draw_count;
1853 	de::MovePtr<Allocation>		m_indirectBufferAlloc;
1854 	Move<VkBuffer>				m_indirectBuffer;
1855 };
1856 
initPrograms(SourceCollections & programCollection) const1857 void AdvGraphicsTest::initPrograms (SourceCollections& programCollection) const
1858 {
1859 	BasicGraphicsTest::initPrograms(programCollection);
1860 
1861 	programCollection.glslSources.add("unused_geo") << glu::GeometrySource(
1862 		"#version 310 es\n"
1863 		"#extension GL_EXT_geometry_shader : enable\n"
1864 		"layout(triangles) in;\n"
1865 		"layout(triangle_strip, max_vertices = 3) out;\n"
1866 		"layout(location = 0) in highp vec4 in_vtxColor[];\n"
1867 		"layout(location = 0) out highp vec4 vtxColor;\n"
1868 		"void main (void)\n"
1869 		"{\n"
1870 		"  for(int ndx=0; ndx<3; ndx++)\n"
1871 		"  {\n"
1872 		"    gl_Position = gl_in[ndx].gl_Position;\n"
1873 		"    vtxColor    = in_vtxColor[ndx];\n"
1874 		"    EmitVertex();\n"
1875 		"  }\n"
1876 		"  EndPrimitive();\n"
1877 		"}\n");
1878 
1879 	programCollection.glslSources.add("basic_tcs") << glu::TessellationControlSource(
1880 		"#version 310 es\n"
1881 		"#extension GL_EXT_tessellation_shader : enable\n"
1882 		"layout(vertices = 3) out;\n"
1883 		"layout(location = 0) in highp vec4 color[];\n"
1884 		"layout(location = 0) out highp vec4 vtxColor[];\n"
1885 		"void main()\n"
1886 		"{\n"
1887 		"  gl_TessLevelOuter[0] = 4.0;\n"
1888 		"  gl_TessLevelOuter[1] = 4.0;\n"
1889 		"  gl_TessLevelOuter[2] = 4.0;\n"
1890 		"  gl_TessLevelInner[0] = 4.0;\n"
1891 		"  gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1892 		"  vtxColor[gl_InvocationID] = color[gl_InvocationID];\n"
1893 		"}\n");
1894 
1895 	programCollection.glslSources.add("basic_tes") << glu::TessellationEvaluationSource(
1896 		"#version 310 es\n"
1897 		"#extension GL_EXT_tessellation_shader : enable\n"
1898 		"layout(triangles, fractional_even_spacing, ccw) in;\n"
1899 		"layout(location = 0) in highp vec4 colors[];\n"
1900 		"layout(location = 0) out highp vec4 vtxColor;\n"
1901 		"void main() \n"
1902 		"{\n"
1903 		"  float u = gl_TessCoord.x;\n"
1904 		"  float v = gl_TessCoord.y;\n"
1905 		"  float w = gl_TessCoord.z;\n"
1906 		"  vec4 pos = vec4(0);\n"
1907 		"  vec4 color = vec4(0);\n"
1908 		"  pos.xyz += u * gl_in[0].gl_Position.xyz;\n"
1909 		"  color.xyz += u * colors[0].xyz;\n"
1910 		"  pos.xyz += v * gl_in[1].gl_Position.xyz;\n"
1911 		"  color.xyz += v * colors[1].xyz;\n"
1912 		"  pos.xyz += w * gl_in[2].gl_Position.xyz;\n"
1913 		"  color.xyz += w * colors[2].xyz;\n"
1914 		"  pos.w = 1.0;\n"
1915 		"  color.w = 1.0;\n"
1916 		"  gl_Position = pos;\n"
1917 		"  vtxColor = color;\n"
1918 		"}\n");
1919 }
1920 
createInstance(Context & context) const1921 TestInstance* AdvGraphicsTest::createInstance (Context& context) const
1922 {
1923 	return new AdvGraphicsTestInstance(context, m_pipelineConstructionType, m_stages, m_inRenderPass, m_hostQueryReset, m_queryResultFlags);
1924 }
1925 
featureSupportCheck(void)1926 void AdvGraphicsTestInstance::featureSupportCheck (void)
1927 {
1928 	for (StageFlagVector::const_iterator it = m_stages.begin(); it != m_stages.end(); it++)
1929 	{
1930 		switch(*it)
1931 		{
1932 			case VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT:
1933 				if (m_features.geometryShader == VK_FALSE)
1934 				{
1935 					TCU_THROW(NotSupportedError, "Geometry Shader Not Supported");
1936 				}
1937 				break;
1938 			case VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT:
1939 			case VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT:
1940 				if (m_features.tessellationShader == VK_FALSE)
1941 				{
1942 					TCU_THROW(NotSupportedError, "Tessellation Not Supported");
1943 				}
1944 				break;
1945 			case VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT:
1946 			default:
1947 				break;
1948 		}
1949 	}
1950 }
1951 
AdvGraphicsTestInstance(Context & context,const PipelineConstructionType pipelineConstructionType,const StageFlagVector stages,const bool inRenderPass,const bool hostQueryReset,const VkQueryResultFlags queryResultFlags)1952 AdvGraphicsTestInstance::AdvGraphicsTestInstance (Context&							context,
1953 												  const PipelineConstructionType	pipelineConstructionType,
1954 												  const StageFlagVector				stages,
1955 												  const bool						inRenderPass,
1956 												  const bool						hostQueryReset,
1957 												  const VkQueryResultFlags			queryResultFlags)
1958 	: BasicGraphicsTestInstance	(context, pipelineConstructionType, stages, inRenderPass, hostQueryReset, queryResultFlags)
1959 	, m_features				(context.getDeviceFeatures())
1960 {
1961 
1962 	const DeviceInterface&	vk = m_context.getDeviceInterface();
1963 
1964 	// If necessary feature is not supported, throw error and fail current test
1965 	featureSupportCheck();
1966 
1967 	// Prepare the indirect draw buffer
1968 	if(m_features.multiDrawIndirect == VK_TRUE)
1969 	{
1970 		m_draw_count = 2;
1971 	}
1972 	else
1973 	{
1974 		m_draw_count = 1;
1975 	}
1976 
1977 	m_indirectBuffer = createBufferAndBindMemory(32u, VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT, &m_indirectBufferAlloc);
1978 
1979 	const VkDrawIndirectCommand indirectCmds[] =
1980 	{
1981 		{
1982 			12u,	// deUint32    vertexCount;
1983 			1u,		// deUint32    instanceCount;
1984 			0u,		// deUint32    firstVertex;
1985 			0u,		// deUint32    firstInstance;
1986 		},
1987 		{
1988 			12u,	// deUint32    vertexCount;
1989 			1u,		// deUint32    instanceCount;
1990 			11u,	// deUint32    firstVertex;
1991 			0u,		// deUint32    firstInstance;
1992 		},
1993 	};
1994 
1995 	// Load data into indirect draw buffer
1996 	deMemcpy(m_indirectBufferAlloc->getHostPtr(), indirectCmds, m_draw_count * sizeof(VkDrawIndirectCommand));
1997 	flushAlloc(vk, m_device, *m_indirectBufferAlloc);
1998 }
1999 
~AdvGraphicsTestInstance(void)2000 AdvGraphicsTestInstance::~AdvGraphicsTestInstance (void)
2001 {
2002 }
2003 
buildPipeline(void)2004 void AdvGraphicsTestInstance::buildPipeline(void)
2005 {
2006 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
2007 
2008 	const std::vector<VkViewport>	viewports	{ makeViewport(m_renderSize) };
2009 	const std::vector<VkRect2D>		scissors	{ makeRect2D(m_renderSize) };
2010 
2011 	ShaderWrapper vertShaderModule	= ShaderWrapper(vk, m_device, m_context.getBinaryCollection().get("color_vert"), 0);
2012 	ShaderWrapper fragShaderModule	= ShaderWrapper(vk, m_device, m_context.getBinaryCollection().get("color_frag"), 0);
2013 	ShaderWrapper tescShaderModule;
2014 	ShaderWrapper teseShaderModule;
2015 	ShaderWrapper geomShaderModule;
2016 
2017 	if (m_features.tessellationShader)
2018 	{
2019 		tescShaderModule	= ShaderWrapper(vk, m_device, m_context.getBinaryCollection().get("basic_tcs"), 0);
2020 		teseShaderModule	= ShaderWrapper(vk, m_device, m_context.getBinaryCollection().get("basic_tes"), 0);
2021 	}
2022 
2023 	if (m_features.geometryShader)
2024 		geomShaderModule	= ShaderWrapper(vk, m_device, m_context.getBinaryCollection().get("unused_geo"), 0);
2025 
2026 	// Create pipeline
2027 	m_graphicsPipeline.setDefaultTopology(m_features.tessellationShader ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
2028 					  .setDefaultRasterizationState()
2029 					  .setDefaultColorBlendState()
2030 					  .setDefaultMultisampleState()
2031 					  .setupVertexInputState(&defaultVertexInputStateParams)
2032 					  .setupPreRasterizationShaderState(viewports,
2033 														scissors,
2034 														m_pipelineLayout,
2035 														*m_renderPass,
2036 														0u,
2037 														vertShaderModule,
2038 														DE_NULL,
2039 														tescShaderModule,
2040 														teseShaderModule,
2041 														geomShaderModule)
2042 					  .setupFragmentShaderState(m_pipelineLayout, *m_renderPass, 0u, fragShaderModule, &defaultDepthStencilStateParams)
2043 					  .setupFragmentOutputState(*m_renderPass)
2044 					  .setMonolithicPipelineLayout(m_pipelineLayout)
2045 					  .buildPipeline();
2046 }
2047 
configCommandBuffer(void)2048 void AdvGraphicsTestInstance::configCommandBuffer (void)
2049 {
2050 	const DeviceInterface&		vk							= m_context.getDeviceInterface();
2051 
2052 	const VkClearValue			attachmentClearValues[2]	=
2053 	{
2054 		defaultClearValue(m_colorFormat),
2055 		defaultClearValue(m_depthFormat),
2056 	};
2057 
2058 	beginCommandBuffer(vk, *m_cmdBuffer, 0u);
2059 
2060 	vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, (VkDependencyFlags)0,
2061 		0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(m_imageLayoutBarriers), m_imageLayoutBarriers);
2062 
2063 	if (!m_hostQueryReset)
2064 		vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
2065 
2066 	m_renderPass.begin(vk, *m_cmdBuffer, makeRect2D(0, 0, m_renderSize.x(), m_renderSize.y()), 2u, attachmentClearValues);
2067 
2068 	m_graphicsPipeline.bind(*m_cmdBuffer);
2069 
2070 	VkDeviceSize offsets = 0u;
2071 	vk.cmdBindVertexBuffers(*m_cmdBuffer, 0u, 1u, &m_vertexBuffer.get(), &offsets);
2072 
2073 	vk.cmdDrawIndirect(*m_cmdBuffer, *m_indirectBuffer, 0u, m_draw_count, sizeof(VkDrawIndirectCommand));
2074 
2075 	if(m_inRenderPass)
2076 	{
2077 	  deUint32 timestampEntry = 0u;
2078 	  for (StageFlagVector::const_iterator it = m_stages.begin(); it != m_stages.end(); it++)
2079 	  {
2080 		  vk.cmdWriteTimestamp(*m_cmdBuffer, *it, *m_queryPool, timestampEntry++);
2081 	  }
2082 	}
2083 
2084 	m_renderPass.end(vk, *m_cmdBuffer);
2085 
2086 	if(!m_inRenderPass)
2087 	{
2088 	  deUint32 timestampEntry = 0u;
2089 	  for (StageFlagVector::const_iterator it = m_stages.begin(); it != m_stages.end(); it++)
2090 	  {
2091 		  vk.cmdWriteTimestamp(*m_cmdBuffer, *it, *m_queryPool, timestampEntry++);
2092 	  }
2093 	}
2094 
2095 	endCommandBuffer(vk, *m_cmdBuffer);
2096 }
2097 
2098 class BasicComputeTest : public TimestampTest
2099 {
2100 public:
BasicComputeTest(tcu::TestContext & testContext,const std::string & name,const TimestampTestParam * param)2101 							BasicComputeTest	(tcu::TestContext&			testContext,
2102 												 const std::string&			name,
2103 												 const TimestampTestParam*	param)
2104 							  : TimestampTest(testContext, name, param)
2105 							  { }
2106 
~BasicComputeTest(void)2107 	virtual					~BasicComputeTest	(void) { }
2108 	virtual void			initPrograms		(SourceCollections& programCollection) const;
2109 	virtual TestInstance*	createInstance		(Context& context) const;
2110 };
2111 
2112 class BasicComputeTestInstance : public TimestampTestInstance
2113 {
2114 public:
2115 					BasicComputeTestInstance	(Context&				context,
2116 												 const StageFlagVector	stages,
2117 												 const bool				inRenderPass,
2118 												 const bool				hostQueryReset,
2119 												 VkQueryResultFlags		VkQueryResultFlags);
2120 
2121 	virtual			~BasicComputeTestInstance	(void);
2122 	virtual void	configCommandBuffer			(void);
2123 protected:
2124 	de::MovePtr<Allocation>     m_inputBufAlloc;
2125 	Move<VkBuffer>              m_inputBuf;
2126 	de::MovePtr<Allocation>     m_outputBufAlloc;
2127 	Move<VkBuffer>              m_outputBuf;
2128 
2129 	Move<VkDescriptorPool>      m_descriptorPool;
2130 	Move<VkDescriptorSet>       m_descriptorSet;
2131 	Move<VkDescriptorSetLayout> m_descriptorSetLayout;
2132 
2133 	Move<VkPipelineLayout>      m_pipelineLayout;
2134 	Move<VkShaderModule>        m_computeShaderModule;
2135 	Move<VkPipeline>            m_computePipelines;
2136 };
2137 
initPrograms(SourceCollections & programCollection) const2138 void BasicComputeTest::initPrograms (SourceCollections& programCollection) const
2139 {
2140 	TimestampTest::initPrograms(programCollection);
2141 
2142 	programCollection.glslSources.add("basic_compute") << glu::ComputeSource(
2143 		"#version 310 es\n"
2144 		"layout(local_size_x = 128) in;\n"
2145 		"layout(std430) buffer;\n"
2146 		"layout(binding = 0) readonly buffer Input0\n"
2147 		"{\n"
2148 		"  vec4 elements[];\n"
2149 		"} input_data0;\n"
2150 		"layout(binding = 1) writeonly buffer Output\n"
2151 		"{\n"
2152 		"  vec4 elements[];\n"
2153 		"} output_data;\n"
2154 		"void main()\n"
2155 		"{\n"
2156 		"  uint ident = gl_GlobalInvocationID.x;\n"
2157 		"  output_data.elements[ident] = input_data0.elements[ident] * input_data0.elements[ident];\n"
2158 		"}");
2159 }
2160 
createInstance(Context & context) const2161 TestInstance* BasicComputeTest::createInstance (Context& context) const
2162 {
2163 	return new BasicComputeTestInstance(context,m_stages,m_inRenderPass, m_hostQueryReset, m_queryResultFlags);
2164 }
2165 
BasicComputeTestInstance(Context & context,const StageFlagVector stages,const bool inRenderPass,const bool hostQueryReset,VkQueryResultFlags VkQueryResultFlags)2166 BasicComputeTestInstance::BasicComputeTestInstance (Context&				context,
2167 												    const StageFlagVector	stages,
2168 												    const bool				inRenderPass,
2169 												    const bool				hostQueryReset,
2170 													VkQueryResultFlags		VkQueryResultFlags)
2171 	: TimestampTestInstance(context, stages, inRenderPass, hostQueryReset, false, VkQueryResultFlags)
2172 {
2173 	const DeviceInterface&	vk			= context.getDeviceInterface();
2174 	const VkDevice			vkDevice	= context.getDevice();
2175 
2176 	// Create buffer object, allocate storage, and generate input data
2177 	const VkDeviceSize		size		= sizeof(tcu::Vec4) * 128u * 128u;
2178 
2179 	m_inputBuf = createBufferAndBindMemory(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, &m_inputBufAlloc);
2180 
2181 	// Load vertices into buffer
2182 	tcu::Vec4*				pVec		= reinterpret_cast<tcu::Vec4*>(m_inputBufAlloc->getHostPtr());
2183 
2184 	for (deUint32 ndx = 0u; ndx < (128u * 128u); ndx++)
2185 	{
2186 		for (deUint32 component = 0u; component < 4u; component++)
2187 		{
2188 			pVec[ndx][component]= (float)(ndx * (component + 1u));
2189 		}
2190 	}
2191 
2192 	flushAlloc(vk, vkDevice, *m_inputBufAlloc);
2193 
2194 	m_outputBuf = createBufferAndBindMemory(size, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, &m_outputBufAlloc);
2195 
2196 	std::vector<VkDescriptorBufferInfo> descriptorInfos;
2197 
2198 	descriptorInfos.push_back(makeDescriptorBufferInfo(*m_inputBuf, 0u, size));
2199 	descriptorInfos.push_back(makeDescriptorBufferInfo(*m_outputBuf, 0u, size));
2200 
2201 	// Create descriptor set layout
2202 	DescriptorSetLayoutBuilder descLayoutBuilder;
2203 
2204 	for (deUint32 bindingNdx = 0u; bindingNdx < 2u; bindingNdx++)
2205 	{
2206 		descLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
2207 	}
2208 
2209 	m_descriptorSetLayout = descLayoutBuilder.build(vk, vkDevice);
2210 
2211 	// Create descriptor pool
2212 	m_descriptorPool = DescriptorPoolBuilder().addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2).build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
2213 
2214 	// Create descriptor set
2215 	const VkDescriptorSetAllocateInfo descriptorSetAllocInfo =
2216 	{
2217 		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,	// VkStructureType                 sType;
2218 		DE_NULL,										// const void*                     pNext;
2219 		*m_descriptorPool,								// VkDescriptorPool                descriptorPool;
2220 		1u,												// deUint32                        setLayoutCount;
2221 		&m_descriptorSetLayout.get(),					// const VkDescriptorSetLayout*    pSetLayouts;
2222 	};
2223 	m_descriptorSet   = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocInfo);
2224 
2225 	DescriptorSetUpdateBuilder  builder;
2226 	for (deUint32 descriptorNdx = 0u; descriptorNdx < 2u; descriptorNdx++)
2227 	{
2228 		builder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(descriptorNdx), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &descriptorInfos[descriptorNdx]);
2229 	}
2230 	builder.update(vk, vkDevice);
2231 
2232 	// Create compute pipeline layout
2233 	const VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo =
2234 	{
2235 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType                 sType;
2236 		DE_NULL,										// const void*                     pNext;
2237 		0u,												// VkPipelineLayoutCreateFlags     flags;
2238 		1u,												// deUint32                        setLayoutCount;
2239 		&m_descriptorSetLayout.get(),					// const VkDescriptorSetLayout*    pSetLayouts;
2240 		0u,												// deUint32                        pushConstantRangeCount;
2241 		DE_NULL,										// const VkPushConstantRange*      pPushConstantRanges;
2242 	};
2243 
2244 	m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutCreateInfo);
2245 
2246 	// Create compute shader
2247 	VkShaderModuleCreateInfo shaderModuleCreateInfo =
2248 	{
2249 		VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,									// VkStructureType             sType;
2250 		DE_NULL,																		// const void*                 pNext;
2251 		0u,																				// VkShaderModuleCreateFlags   flags;
2252 		m_context.getBinaryCollection().get("basic_compute").getSize(),					// deUintptr                   codeSize;
2253 		(deUint32*)m_context.getBinaryCollection().get("basic_compute").getBinary(),	// const deUint32*             pCode;
2254 
2255 	};
2256 
2257 	m_computeShaderModule = createShaderModule(vk, vkDevice, &shaderModuleCreateInfo);
2258 
2259 	// Create compute pipeline
2260 	const VkPipelineShaderStageCreateInfo stageCreateInfo =
2261 	{
2262 		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	// VkStructureType                     sType;
2263 		DE_NULL,												// const void*                         pNext;
2264 		0u,														// VkPipelineShaderStageCreateFlags    flags;
2265 		VK_SHADER_STAGE_COMPUTE_BIT,							// VkShaderStageFlagBits               stage;
2266 		*m_computeShaderModule,									// VkShaderModule                      module;
2267 		"main",													// const char*                         pName;
2268 		DE_NULL,												// const VkSpecializationInfo*         pSpecializationInfo;
2269 	};
2270 
2271 	const VkComputePipelineCreateInfo pipelineCreateInfo =
2272 	{
2273 		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,	// VkStructureType                 sType;
2274 		DE_NULL,										// const void*                     pNext;
2275 		0u,												// VkPipelineCreateFlags           flags;
2276 		stageCreateInfo,								// VkPipelineShaderStageCreateInfo stage;
2277 		*m_pipelineLayout,								// VkPipelineLayout                layout;
2278 		(VkPipeline)0,									// VkPipeline                      basePipelineHandle;
2279 		0u,												// deInt32                         basePipelineIndex;
2280 	};
2281 
2282 	m_computePipelines = createComputePipeline(vk, vkDevice, (VkPipelineCache)0u, &pipelineCreateInfo);
2283 }
2284 
~BasicComputeTestInstance(void)2285 BasicComputeTestInstance::~BasicComputeTestInstance (void)
2286 {
2287 }
2288 
configCommandBuffer(void)2289 void BasicComputeTestInstance::configCommandBuffer (void)
2290 {
2291 	const DeviceInterface& vk = m_context.getDeviceInterface();
2292 
2293 	beginCommandBuffer(vk, *m_cmdBuffer, 0u);
2294 
2295 	if (!m_hostQueryReset)
2296 		vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
2297 
2298 	vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_computePipelines);
2299 	vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *m_pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
2300 	vk.cmdDispatch(*m_cmdBuffer, 128u, 1u, 1u);
2301 
2302 	deUint32 timestampEntry = 0u;
2303 	for (StageFlagVector::const_iterator it = m_stages.begin(); it != m_stages.end(); it++)
2304 	{
2305 		vk.cmdWriteTimestamp(*m_cmdBuffer, *it, *m_queryPool, timestampEntry++);
2306 	}
2307 
2308 	endCommandBuffer(vk, *m_cmdBuffer);
2309 }
2310 
2311 class TransferTest : public TimestampTest
2312 {
2313 public:
2314 							TransferTest	(tcu::TestContext&			testContext,
2315 											 const std::string&			name,
2316 											 const TimestampTestParam*	param);
2317 
~TransferTest(void)2318 	virtual					~TransferTest	(void) { }
2319 	virtual void			initPrograms	(SourceCollections& programCollection) const;
2320 	virtual TestInstance*	createInstance	(Context& context) const;
2321 
2322 protected:
2323 	TransferMethod			m_method;
2324 };
2325 
2326 class TransferTestInstance : public TimestampTestInstance
2327 {
2328 public:
2329 					TransferTestInstance	(Context&					context,
2330 											 const StageFlagVector		stages,
2331 											 const bool					inRenderPass,
2332 											 const bool					hostQueryReset,
2333 											 const bool					transferOnlyQueue,
2334 											 const TransferMethod		method,
2335 											 const VkQueryResultFlags	queryResultFlags);
2336 
2337 	virtual			~TransferTestInstance	(void);
2338 	virtual void	configCommandBuffer		(void);
2339 	virtual void	initialImageTransition	(VkCommandBuffer			cmdBuffer,
2340 											 VkImage					image,
2341 											 VkImageSubresourceRange	subRange,
2342 											 VkImageLayout				layout);
2343 protected:
2344 	TransferMethod			m_method;
2345 
2346 	VkDeviceSize			m_bufSize;
2347 	Move<VkBuffer>			m_srcBuffer;
2348 	Move<VkBuffer>			m_dstBuffer;
2349 	de::MovePtr<Allocation>	m_srcBufferAlloc;
2350 	de::MovePtr<Allocation>	m_dstBufferAlloc;
2351 
2352 	VkFormat				m_imageFormat;
2353 	deInt32					m_imageWidth;
2354 	deInt32					m_imageHeight;
2355 	VkDeviceSize			m_imageSize;
2356 	Move<VkImage>			m_srcImage;
2357 	Move<VkImage>			m_dstImage;
2358 	Move<VkImage>			m_depthImage;
2359 	Move<VkImage>			m_msImage;
2360 	de::MovePtr<Allocation>	m_srcImageAlloc;
2361 	de::MovePtr<Allocation>	m_dstImageAlloc;
2362 	de::MovePtr<Allocation>	m_depthImageAlloc;
2363 	de::MovePtr<Allocation>	m_msImageAlloc;
2364 };
2365 
TransferTest(tcu::TestContext & testContext,const std::string & name,const TimestampTestParam * param)2366 TransferTest::TransferTest (tcu::TestContext&			testContext,
2367 							const std::string&			name,
2368 							const TimestampTestParam*	param)
2369 	: TimestampTest(testContext, name, param)
2370 {
2371 	const TransferTimestampTestParam* transferParam = dynamic_cast<const TransferTimestampTestParam*>(param);
2372 	m_method = transferParam->getMethod();
2373 }
2374 
initPrograms(SourceCollections & programCollection) const2375 void TransferTest::initPrograms (SourceCollections& programCollection) const
2376 {
2377 	TimestampTest::initPrograms(programCollection);
2378 }
2379 
createInstance(Context & context) const2380 TestInstance* TransferTest::createInstance (Context& context) const
2381 {
2382   return new TransferTestInstance(context, m_stages, m_inRenderPass, m_hostQueryReset, m_transferOnlyQueue, m_method, m_queryResultFlags);
2383 }
2384 
TransferTestInstance(Context & context,const StageFlagVector stages,const bool inRenderPass,const bool hostQueryReset,const bool transferOnlyQueue,const TransferMethod method,const VkQueryResultFlags queryResultFlags)2385 TransferTestInstance::TransferTestInstance (Context&					context,
2386 											const StageFlagVector		stages,
2387 											const bool					inRenderPass,
2388 											const bool					hostQueryReset,
2389 											const bool					transferOnlyQueue,
2390 											const TransferMethod		method,
2391 											const VkQueryResultFlags	queryResultFlags)
2392 	: TimestampTestInstance(context, stages, inRenderPass, hostQueryReset, transferOnlyQueue, queryResultFlags)
2393 	, m_method(method)
2394 	, m_bufSize((queryResultFlags & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) ? 512u : 256u)
2395 	, m_imageFormat(VK_FORMAT_R8G8B8A8_UNORM)
2396 	, m_imageWidth(4u)
2397 	, m_imageHeight(4u)
2398 	, m_imageSize(256u)
2399 {
2400 	const DeviceInterface&	vk			= context.getDeviceInterface();
2401 
2402 	// Create src buffer
2403 	m_srcBuffer = createBufferAndBindMemory(m_bufSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, &m_srcBufferAlloc);
2404 
2405 	// Init the source buffer memory
2406 	char* pBuf = reinterpret_cast<char*>(m_srcBufferAlloc->getHostPtr());
2407 	deMemset(pBuf, 0xFF, sizeof(char)*(size_t)m_bufSize);
2408 	flushAlloc(vk, m_device, *m_srcBufferAlloc);
2409 
2410 	// Create dst buffer
2411 	m_dstBuffer	= createBufferAndBindMemory(m_bufSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, &m_dstBufferAlloc);
2412 
2413 	// Create src/dst/depth image
2414 	m_srcImage		= createImage2DAndBindMemory(m_imageFormat, m_imageWidth, m_imageHeight,
2415 												 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
2416 												 VK_SAMPLE_COUNT_1_BIT,
2417 												 &m_srcImageAlloc);
2418 	m_dstImage		= createImage2DAndBindMemory(m_imageFormat, m_imageWidth, m_imageHeight,
2419 												 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
2420 												 VK_SAMPLE_COUNT_1_BIT,
2421 												 &m_dstImageAlloc);
2422 	m_depthImage	= createImage2DAndBindMemory(VK_FORMAT_D16_UNORM, m_imageWidth, m_imageHeight,
2423 												 VK_IMAGE_USAGE_TRANSFER_DST_BIT,
2424 												 VK_SAMPLE_COUNT_1_BIT,
2425 												 &m_depthImageAlloc);
2426 	m_msImage		= createImage2DAndBindMemory(m_imageFormat, m_imageWidth, m_imageHeight,
2427 												 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
2428 												 VK_SAMPLE_COUNT_4_BIT,
2429 												 &m_msImageAlloc);
2430 }
2431 
~TransferTestInstance(void)2432 TransferTestInstance::~TransferTestInstance (void)
2433 {
2434 }
2435 
configCommandBuffer(void)2436 void TransferTestInstance::configCommandBuffer (void)
2437 {
2438 	const DeviceInterface& vk = m_context.getDeviceInterface();
2439 
2440 	beginCommandBuffer(vk, *m_cmdBuffer, 0u);
2441 
2442 	// Initialize buffer/image
2443 	vk.cmdFillBuffer(*m_cmdBuffer, *m_dstBuffer, 0u, m_bufSize, 0x0);
2444 
2445 	const VkClearColorValue srcClearValue =
2446 	{
2447 		{1.0f, 1.0f, 1.0f, 1.0f}
2448 	};
2449 	const VkClearColorValue dstClearValue =
2450 	{
2451 		{0.0f, 0.0f, 0.0f, 0.0f}
2452 	};
2453 	const struct VkImageSubresourceRange subRangeColor =
2454 	{
2455 		VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags  aspectMask;
2456 		0u,							// deUint32            baseMipLevel;
2457 		1u,							// deUint32            mipLevels;
2458 		0u,							// deUint32            baseArrayLayer;
2459 		1u,							// deUint32            arraySize;
2460 	};
2461 	const struct VkImageSubresourceRange subRangeDepth =
2462 	{
2463 		VK_IMAGE_ASPECT_DEPTH_BIT,	// VkImageAspectFlags  aspectMask;
2464 		0u,							// deUint32            baseMipLevel;
2465 		1u,							// deUint32            mipLevels;
2466 		0u,							// deUint32            baseArrayLayer;
2467 		1u,							// deUint32            arraySize;
2468 	};
2469 
2470 	initialImageTransition(*m_cmdBuffer, *m_srcImage, subRangeColor, VK_IMAGE_LAYOUT_GENERAL);
2471 	initialImageTransition(*m_cmdBuffer, *m_dstImage, subRangeColor, VK_IMAGE_LAYOUT_GENERAL);
2472 
2473 	if (!m_transferOnlyQueue)
2474 	{
2475 		vk.cmdClearColorImage(*m_cmdBuffer, *m_srcImage, VK_IMAGE_LAYOUT_GENERAL, &srcClearValue, 1u, &subRangeColor);
2476 		vk.cmdClearColorImage(*m_cmdBuffer, *m_dstImage, VK_IMAGE_LAYOUT_GENERAL, &dstClearValue, 1u, &subRangeColor);
2477 	}
2478 
2479 	// synchronize the Clear commands before starting any copy
2480 	const vk::VkMemoryBarrier barrier =
2481 	{
2482 		vk::VK_STRUCTURE_TYPE_MEMORY_BARRIER,							// VkStructureType	sType;
2483 		DE_NULL,														// const void*		pNext;
2484 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,								// VkAccessFlags	srcAccessMask;
2485 		vk::VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags	dstAccessMask;
2486 	};
2487 	vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1u, &barrier, 0u, DE_NULL, 0u, DE_NULL);
2488 
2489 	if (!m_hostQueryReset)
2490 		vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
2491 
2492 	// Copy Operations
2493 	const VkImageSubresourceLayers imgSubResCopy =
2494 	{
2495 		VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags  aspectMask;
2496 		0u,							// deUint32            mipLevel;
2497 		0u,							// deUint32            baseArrayLayer;
2498 		1u,							// deUint32            layerCount;
2499 	};
2500 
2501 	const VkOffset3D nullOffset  = {0u, 0u, 0u};
2502 	const VkExtent3D imageExtent = {(deUint32)m_imageWidth, (deUint32)m_imageHeight, 1u};
2503 	const VkOffset3D imageOffset = {(int)m_imageWidth, (int)m_imageHeight, 1};
2504 
2505 	switch(m_method)
2506 	{
2507 		case TRANSFER_METHOD_COPY_BUFFER:
2508 			{
2509 				const VkBufferCopy  copyBufRegion =
2510 					{
2511 						0u,			// VkDeviceSize    srcOffset;
2512 						0u,			// VkDeviceSize    destOffset;
2513 						m_bufSize,	// VkDeviceSize    copySize;
2514 					};
2515 
2516 				vk.cmdCopyBuffer(*m_cmdBuffer, *m_srcBuffer, *m_dstBuffer, 1u, &copyBufRegion);
2517 				break;
2518 			}
2519 		case TRANSFER_METHOD_COPY_IMAGE:
2520 			{
2521 				const VkImageCopy copyImageRegion =
2522 				{
2523 					imgSubResCopy,	// VkImageSubresourceCopy  srcSubresource;
2524 					nullOffset,		// VkOffset3D              srcOffset;
2525 					imgSubResCopy,	// VkImageSubresourceCopy  destSubresource;
2526 					nullOffset,		// VkOffset3D              destOffset;
2527 					imageExtent,	// VkExtent3D              extent;
2528 
2529 				};
2530 
2531 				vk.cmdCopyImage(*m_cmdBuffer, *m_srcImage, VK_IMAGE_LAYOUT_GENERAL, *m_dstImage, VK_IMAGE_LAYOUT_GENERAL, 1u, &copyImageRegion);
2532 				break;
2533 			}
2534 		case TRANSFER_METHOD_COPY_BUFFER_TO_IMAGE:
2535 			{
2536 				const VkBufferImageCopy bufImageCopy =
2537 				{
2538 					0u,							// VkDeviceSize            bufferOffset;
2539 					(deUint32)m_imageWidth,		// deUint32                bufferRowLength;
2540 					(deUint32)m_imageHeight,	// deUint32                bufferImageHeight;
2541 					imgSubResCopy,				// VkImageSubresourceCopy  imageSubresource;
2542 					nullOffset,					// VkOffset3D              imageOffset;
2543 					imageExtent,				// VkExtent3D              imageExtent;
2544 				};
2545 
2546 				vk.cmdCopyBufferToImage(*m_cmdBuffer, *m_srcBuffer, *m_dstImage, VK_IMAGE_LAYOUT_GENERAL, 1u, &bufImageCopy);
2547 				break;
2548 			}
2549 		case TRANSFER_METHOD_COPY_IMAGE_TO_BUFFER:
2550 			{
2551 				const VkBufferImageCopy imgBufferCopy =
2552 				{
2553 					0u,							// VkDeviceSize            bufferOffset;
2554 					(deUint32)m_imageWidth,		// deUint32                bufferRowLength;
2555 					(deUint32)m_imageHeight,	// deUint32                bufferImageHeight;
2556 					imgSubResCopy,				// VkImageSubresourceCopy  imageSubresource;
2557 					nullOffset,					// VkOffset3D              imageOffset;
2558 					imageExtent,				// VkExtent3D              imageExtent;
2559 				};
2560 
2561 				vk.cmdCopyImageToBuffer(*m_cmdBuffer, *m_srcImage, VK_IMAGE_LAYOUT_GENERAL, *m_dstBuffer, 1u, &imgBufferCopy);
2562 				break;
2563 			}
2564 		case TRANSFER_METHOD_BLIT_IMAGE:
2565 			{
2566 				const VkImageBlit imageBlt =
2567 				{
2568 					imgSubResCopy,	// VkImageSubresourceCopy  srcSubresource;
2569 					{
2570 						nullOffset,
2571 						imageOffset,
2572 					},
2573 					imgSubResCopy,	// VkImageSubresourceCopy  destSubresource;
2574 					{
2575 						nullOffset,
2576 						imageOffset,
2577 					}
2578 				};
2579 
2580 				vk.cmdBlitImage(*m_cmdBuffer, *m_srcImage, VK_IMAGE_LAYOUT_GENERAL, *m_dstImage, VK_IMAGE_LAYOUT_GENERAL, 1u, &imageBlt, VK_FILTER_NEAREST);
2581 				break;
2582 			}
2583 		case TRANSFER_METHOD_CLEAR_COLOR_IMAGE:
2584 			{
2585 				vk.cmdClearColorImage(*m_cmdBuffer, *m_dstImage, VK_IMAGE_LAYOUT_GENERAL, &srcClearValue, 1u, &subRangeColor);
2586 				break;
2587 			}
2588 		case TRANSFER_METHOD_CLEAR_DEPTH_STENCIL_IMAGE:
2589 			{
2590 				initialImageTransition(*m_cmdBuffer, *m_depthImage, subRangeDepth, VK_IMAGE_LAYOUT_GENERAL);
2591 
2592 				const VkClearDepthStencilValue clearDSValue =
2593 				{
2594 					1.0f,	// float       depth;
2595 					0u,		// deUint32    stencil;
2596 				};
2597 
2598 				vk.cmdClearDepthStencilImage(*m_cmdBuffer, *m_depthImage, VK_IMAGE_LAYOUT_GENERAL, &clearDSValue, 1u, &subRangeDepth);
2599 				break;
2600 			}
2601 		case TRANSFER_METHOD_FILL_BUFFER:
2602 			{
2603 				vk.cmdFillBuffer(*m_cmdBuffer, *m_dstBuffer, 0u, m_bufSize, 0x0);
2604 				break;
2605 			}
2606 		case TRANSFER_METHOD_UPDATE_BUFFER:
2607 			{
2608 				const deUint32 data[] =
2609 				{
2610 					0xdeadbeef, 0xabcdef00, 0x12345678
2611 				};
2612 
2613 				vk.cmdUpdateBuffer(*m_cmdBuffer, *m_dstBuffer, 0x10, sizeof(data), data);
2614 				break;
2615 			}
2616 		case TRANSFER_METHOD_COPY_QUERY_POOL_RESULTS:
2617 		case TRANSFER_METHOD_COPY_QUERY_POOL_RESULTS_STRIDE_ZERO:
2618 			{
2619 				vk.cmdWriteTimestamp(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, *m_queryPool, 0u);
2620 				VkDeviceSize copyStride = m_method == TRANSFER_METHOD_COPY_QUERY_POOL_RESULTS_STRIDE_ZERO ? 0u : 8u;
2621 				vk.cmdCopyQueryPoolResults(*m_cmdBuffer, *m_queryPool, 0u, 1u, *m_dstBuffer, 0u, copyStride, VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
2622 
2623 				const vk::VkBufferMemoryBarrier bufferBarrier =
2624 				{
2625 					vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
2626 					DE_NULL,										// const void*		pNext;
2627 					vk::VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
2628 					vk::VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
2629 					VK_QUEUE_FAMILY_IGNORED,						// deUint32			srcQueueFamilyIndex;
2630 					VK_QUEUE_FAMILY_IGNORED,						// deUint32			dstQueueFamilyIndex;
2631 					*m_dstBuffer,									// VkBuffer			buffer;
2632 					0ull,											// VkDeviceSize		offset;
2633 					VK_WHOLE_SIZE									// VkDeviceSize		size;
2634 				};
2635 
2636 				vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u,
2637 									  0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
2638 
2639 				vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, 1u);
2640 				break;
2641 			}
2642 		case TRANSFER_METHOD_RESOLVE_IMAGE:
2643 			{
2644 				const VkImageResolve imageResolve =
2645 				{
2646 					imgSubResCopy,                              // VkImageSubresourceLayers  srcSubresource;
2647 					nullOffset,                                 // VkOffset3D                srcOffset;
2648 					imgSubResCopy,                              // VkImageSubresourceLayers  destSubresource;
2649 					nullOffset,                                 // VkOffset3D                destOffset;
2650 					imageExtent,                                // VkExtent3D                extent;
2651 				};
2652 
2653 				initialImageTransition(*m_cmdBuffer, *m_msImage, subRangeColor, VK_IMAGE_LAYOUT_GENERAL);
2654 				vk.cmdClearColorImage(*m_cmdBuffer, *m_msImage, VK_IMAGE_LAYOUT_GENERAL, &srcClearValue, 1u, &subRangeColor);
2655 				vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 1u, &barrier, 0u, DE_NULL, 0u, DE_NULL);
2656 				vk.cmdResolveImage(*m_cmdBuffer, *m_msImage, VK_IMAGE_LAYOUT_GENERAL, *m_dstImage, VK_IMAGE_LAYOUT_GENERAL, 1u, &imageResolve);
2657 				break;
2658 			}
2659 		default:
2660 			DE_FATAL("Unknown Transfer Method!");
2661 			break;
2662 	}
2663 
2664 	deUint32 timestampEntry = 0u;
2665 
2666 	for (StageFlagVector::const_iterator it = m_stages.begin(); it != m_stages.end(); it++)
2667 	{
2668 		vk.cmdWriteTimestamp(*m_cmdBuffer, *it, *m_queryPool, timestampEntry++);
2669 	}
2670 
2671 	endCommandBuffer(vk, *m_cmdBuffer);
2672 }
2673 
initialImageTransition(VkCommandBuffer cmdBuffer,VkImage image,VkImageSubresourceRange subRange,VkImageLayout layout)2674 void TransferTestInstance::initialImageTransition (VkCommandBuffer cmdBuffer, VkImage image, VkImageSubresourceRange subRange, VkImageLayout layout)
2675 {
2676 	const DeviceInterface&		vk				= m_context.getDeviceInterface();
2677 
2678 	const VkImageMemoryBarrier	imageMemBarrier	=
2679 	{
2680 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType          sType;
2681 		DE_NULL,								// const void*              pNext;
2682 		0u,										// VkAccessFlags            srcAccessMask;
2683 		VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags            dstAccessMask;
2684 		VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout            oldLayout;
2685 		layout,									// VkImageLayout            newLayout;
2686 		VK_QUEUE_FAMILY_IGNORED,				// uint32_t                 srcQueueFamilyIndex;
2687 		VK_QUEUE_FAMILY_IGNORED,				// uint32_t                 dstQueueFamilyIndex;
2688 		image,									// VkImage                  image;
2689 		subRange								// VkImageSubresourceRange  subresourceRange;
2690 	};
2691 
2692 	vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1, &imageMemBarrier);
2693 }
2694 
2695 class FillBufferBeforeCopyTest : public vkt::TestCase
2696 {
2697 public:
FillBufferBeforeCopyTest(tcu::TestContext & testContext,const std::string & name)2698 	FillBufferBeforeCopyTest(tcu::TestContext& testContext,
2699 		const std::string& name)
2700 		: vkt::TestCase(testContext, name)
2701 	{ }
~FillBufferBeforeCopyTest(void)2702 	virtual               ~FillBufferBeforeCopyTest(void) { }
2703 	virtual void          initPrograms(SourceCollections& programCollection) const;
2704 	virtual TestInstance* createInstance(Context& context) const;
2705 };
2706 
2707 class FillBufferBeforeCopyTestInstance : public vkt::TestInstance
2708 {
2709 public:
2710 	FillBufferBeforeCopyTestInstance(Context& context);
~FillBufferBeforeCopyTestInstance(void)2711 	virtual					~FillBufferBeforeCopyTestInstance(void) { }
2712 	virtual tcu::TestStatus	iterate(void);
2713 protected:
2714 	struct TimestampWithAvailability
2715 	{
2716 		deUint64 timestamp;
2717 		deUint64 availability;
2718 	};
2719 
2720 	Move<VkCommandPool>		m_cmdPool;
2721 	Move<VkCommandBuffer>	m_cmdBuffer;
2722 	Move<VkQueryPool>		m_queryPool;
2723 
2724 	Move<VkBuffer>			m_resultBuffer;
2725 	de::MovePtr<Allocation>	m_resultBufferMemory;
2726 };
2727 
initPrograms(SourceCollections & programCollection) const2728 void FillBufferBeforeCopyTest::initPrograms(SourceCollections& programCollection) const
2729 {
2730 	vkt::TestCase::initPrograms(programCollection);
2731 }
2732 
createInstance(Context & context) const2733 TestInstance* FillBufferBeforeCopyTest::createInstance(Context& context) const
2734 {
2735 	return new FillBufferBeforeCopyTestInstance(context);
2736 }
2737 
FillBufferBeforeCopyTestInstance(Context & context)2738 FillBufferBeforeCopyTestInstance::FillBufferBeforeCopyTestInstance(Context& context)
2739 	: vkt::TestInstance(context)
2740 {
2741 	const DeviceInterface& vk = context.getDeviceInterface();
2742 	const VkDevice			vkDevice = context.getDevice();
2743 	const deUint32			queueFamilyIndex = context.getUniversalQueueFamilyIndex();
2744 	Allocator& allocator = m_context.getDefaultAllocator();
2745 
2746 	// Check support for timestamp queries
2747 	checkTimestampsSupported(context.getInstanceInterface(), context.getPhysicalDevice(), queueFamilyIndex);
2748 
2749 	const VkQueryPoolCreateInfo queryPoolParams =
2750 	{
2751 		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,	// VkStructureType               sType;
2752 		DE_NULL,									// const void*                   pNext;
2753 		0u,											// VkQueryPoolCreateFlags        flags;
2754 		VK_QUERY_TYPE_TIMESTAMP,					// VkQueryType                   queryType;
2755 		1u,											// deUint32                      entryCount;
2756 		0u,											// VkQueryPipelineStatisticFlags pipelineStatistics;
2757 	};
2758 
2759 	m_queryPool = createQueryPool(vk, vkDevice, &queryPoolParams);
2760 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
2761 	m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2762 
2763 	// Create results buffer.
2764 	const VkBufferCreateInfo bufferCreateInfo =
2765 	{
2766 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
2767 		DE_NULL,									// const void*			pNext;
2768 		0u,											// VkBufferCreateFlags	flags;
2769 		sizeof(TimestampWithAvailability),			// VkDeviceSize			size;
2770 		VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
2771 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
2772 		1u,											// deUint32				queueFamilyIndexCount;
2773 		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
2774 	};
2775 
2776 	m_resultBuffer = createBuffer(vk, vkDevice, &bufferCreateInfo);
2777 	m_resultBufferMemory = allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_resultBuffer), MemoryRequirement::HostVisible);
2778 	VK_CHECK(vk.bindBufferMemory(vkDevice, *m_resultBuffer, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset()));
2779 
2780 	const vk::VkBufferMemoryBarrier fillBufferBarrier =
2781 	{
2782 		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
2783 		DE_NULL,										// const void*		pNext;
2784 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
2785 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	dstAccessMask;
2786 		VK_QUEUE_FAMILY_IGNORED,						// deUint32			srcQueueFamilyIndex;
2787 		VK_QUEUE_FAMILY_IGNORED,						// deUint32			dstQueueFamilyIndex;
2788 		*m_resultBuffer,								// VkBuffer			buffer;
2789 		0ull,											// VkDeviceSize		offset;
2790 		VK_WHOLE_SIZE									// VkDeviceSize		size;
2791 	};
2792 
2793 	const vk::VkBufferMemoryBarrier bufferBarrier =
2794 	{
2795 		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
2796 		DE_NULL,										// const void*		pNext;
2797 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
2798 		vk::VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
2799 		VK_QUEUE_FAMILY_IGNORED,						// deUint32			srcQueueFamilyIndex;
2800 		VK_QUEUE_FAMILY_IGNORED,						// deUint32			dstQueueFamilyIndex;
2801 		*m_resultBuffer,								// VkBuffer			buffer;
2802 		0ull,											// VkDeviceSize		offset;
2803 		VK_WHOLE_SIZE									// VkDeviceSize		size;
2804 	};
2805 
2806 	// Prepare command buffer.
2807 	beginCommandBuffer(vk, *m_cmdBuffer, 0u);
2808 	vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, 1u);
2809 	vk.cmdFillBuffer(*m_cmdBuffer, *m_resultBuffer, 0u, bufferCreateInfo.size, 0u);
2810 	vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 1u, &fillBufferBarrier, 0u, DE_NULL);
2811 	vk.cmdWriteTimestamp(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, *m_queryPool, 0u);
2812 	vk.cmdCopyQueryPoolResults(*m_cmdBuffer, *m_queryPool, 0u, 1u, *m_resultBuffer, 0u, sizeof(TimestampWithAvailability), (VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT));
2813 	vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
2814 	endCommandBuffer(vk, *m_cmdBuffer);
2815 }
2816 
iterate(void)2817 tcu::TestStatus FillBufferBeforeCopyTestInstance::iterate(void)
2818 {
2819 	const DeviceInterface& vk = m_context.getDeviceInterface();
2820 	const VkDevice				vkDevice = m_context.getDevice();
2821 	const VkQueue				queue = m_context.getUniversalQueue();
2822 	TimestampWithAvailability	ta;
2823 
2824 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
2825 	invalidateAlloc(vk, vkDevice, *m_resultBufferMemory);
2826 	deMemcpy(&ta, m_resultBufferMemory->getHostPtr(), sizeof(ta));
2827 	if (ta.availability) {
2828 		if (ta.timestamp == 0) {
2829 			return tcu::TestStatus::fail("Timestamp not written");
2830 		}
2831 	}
2832 	return tcu::TestStatus::pass("Pass");
2833 }
2834 
2835 class ResetTimestampQueryBeforeCopyTest : public vkt::TestCase
2836 {
2837 public:
ResetTimestampQueryBeforeCopyTest(tcu::TestContext & testContext,const std::string & name)2838 	ResetTimestampQueryBeforeCopyTest							(tcu::TestContext&	testContext,
2839 																 const std::string&	name)
2840 		: vkt::TestCase(testContext, name)
2841 		{ }
~ResetTimestampQueryBeforeCopyTest(void)2842 	virtual               ~ResetTimestampQueryBeforeCopyTest	(void) { }
2843 	virtual void          initPrograms							(SourceCollections&	programCollection) const;
2844 	virtual TestInstance* createInstance						(Context&			context) const;
2845 };
2846 
2847 class ResetTimestampQueryBeforeCopyTestInstance : public vkt::TestInstance
2848 {
2849 public:
2850 							ResetTimestampQueryBeforeCopyTestInstance	(Context& context);
~ResetTimestampQueryBeforeCopyTestInstance(void)2851 	virtual					~ResetTimestampQueryBeforeCopyTestInstance	(void) { }
2852 	virtual tcu::TestStatus	iterate										(void);
2853 protected:
2854 	struct TimestampWithAvailability
2855 	{
2856 		deUint64 timestamp;
2857 		deUint64 availability;
2858 	};
2859 
2860 	Move<VkCommandPool>		m_cmdPool;
2861 	Move<VkCommandBuffer>	m_cmdBuffer;
2862 	Move<VkQueryPool>		m_queryPool;
2863 
2864 	Move<VkBuffer>			m_resultBuffer;
2865 	de::MovePtr<Allocation>	m_resultBufferMemory;
2866 };
2867 
initPrograms(SourceCollections & programCollection) const2868 void ResetTimestampQueryBeforeCopyTest::initPrograms (SourceCollections& programCollection) const
2869 {
2870 	vkt::TestCase::initPrograms(programCollection);
2871 }
2872 
createInstance(Context & context) const2873 TestInstance* ResetTimestampQueryBeforeCopyTest::createInstance (Context& context) const
2874 {
2875 	return new ResetTimestampQueryBeforeCopyTestInstance(context);
2876 }
2877 
ResetTimestampQueryBeforeCopyTestInstance(Context & context)2878 ResetTimestampQueryBeforeCopyTestInstance::ResetTimestampQueryBeforeCopyTestInstance (Context& context)
2879 	: vkt::TestInstance(context)
2880 {
2881 	const DeviceInterface&	vk					= context.getDeviceInterface();
2882 	const VkDevice			vkDevice			= context.getDevice();
2883 	const deUint32			queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
2884 	Allocator&				allocator			= m_context.getDefaultAllocator();
2885 
2886 	// Check support for timestamp queries
2887 	checkTimestampsSupported(context.getInstanceInterface(), context.getPhysicalDevice(), queueFamilyIndex);
2888 
2889 	const VkQueryPoolCreateInfo queryPoolParams =
2890 	{
2891 		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,	// VkStructureType               sType;
2892 		DE_NULL,									// const void*                   pNext;
2893 		0u,											// VkQueryPoolCreateFlags        flags;
2894 		VK_QUERY_TYPE_TIMESTAMP,					// VkQueryType                   queryType;
2895 		1u,											// deUint32                      entryCount;
2896 		0u,											// VkQueryPipelineStatisticFlags pipelineStatistics;
2897 	};
2898 
2899 	m_queryPool		= createQueryPool(vk, vkDevice, &queryPoolParams);
2900 	m_cmdPool		= createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
2901 	m_cmdBuffer		= allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
2902 
2903 	// Create results buffer.
2904 	const VkBufferCreateInfo bufferCreateInfo =
2905 	{
2906 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
2907 		DE_NULL,									// const void*			pNext;
2908 		0u,											// VkBufferCreateFlags	flags;
2909 		sizeof(TimestampWithAvailability),			// VkDeviceSize			size;
2910 		VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
2911 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
2912 		1u,											// deUint32				queueFamilyIndexCount;
2913 		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
2914 	};
2915 
2916 	m_resultBuffer			= createBuffer(vk, vkDevice, &bufferCreateInfo);
2917 	m_resultBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_resultBuffer), MemoryRequirement::HostVisible);
2918 	VK_CHECK(vk.bindBufferMemory(vkDevice, *m_resultBuffer, m_resultBufferMemory->getMemory(), m_resultBufferMemory->getOffset()));
2919 
2920 	const vk::VkBufferMemoryBarrier bufferBarrier =
2921 	{
2922 		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
2923 		DE_NULL,										// const void*		pNext;
2924 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
2925 		vk::VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
2926 		VK_QUEUE_FAMILY_IGNORED,						// deUint32			srcQueueFamilyIndex;
2927 		VK_QUEUE_FAMILY_IGNORED,						// deUint32			dstQueueFamilyIndex;
2928 		*m_resultBuffer,								// VkBuffer			buffer;
2929 		0ull,											// VkDeviceSize		offset;
2930 		VK_WHOLE_SIZE									// VkDeviceSize		size;
2931 	};
2932 
2933 	// Prepare command buffer.
2934 	beginCommandBuffer(vk, *m_cmdBuffer, 0u);
2935 	vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, 1u);
2936 	vk.cmdWriteTimestamp(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, *m_queryPool, 0u);
2937 	vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, 1u);
2938 	vk.cmdCopyQueryPoolResults(*m_cmdBuffer, *m_queryPool, 0u, 1u, *m_resultBuffer, 0u, sizeof(TimestampWithAvailability), (VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT));
2939 	vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
2940 	endCommandBuffer(vk, *m_cmdBuffer);
2941 }
2942 
iterate(void)2943 tcu::TestStatus ResetTimestampQueryBeforeCopyTestInstance::iterate (void)
2944 {
2945 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
2946 	const VkDevice				vkDevice	= m_context.getDevice();
2947 	const VkQueue				queue		= m_context.getUniversalQueue();
2948 	TimestampWithAvailability	ta;
2949 
2950 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
2951 	invalidateAlloc(vk, vkDevice, *m_resultBufferMemory);
2952 	deMemcpy(&ta, m_resultBufferMemory->getHostPtr(), sizeof(ta));
2953 	return ((ta.availability != 0)? tcu::TestStatus::fail("Availability bit nonzero after resetting query") : tcu::TestStatus::pass("Pass"));
2954 }
2955 
2956 
2957 class TwoCmdBuffersTest : public TimestampTest
2958 {
2959 public:
TwoCmdBuffersTest(tcu::TestContext & testContext,const std::string & name,const TwoCmdBuffersTestParam * param)2960 							TwoCmdBuffersTest	(tcu::TestContext&				testContext,
2961 												 const std::string&				name,
2962 												 const TwoCmdBuffersTestParam*	param)
2963 : TimestampTest (testContext, name, param), m_cmdBufferLevel(param->getCmdBufferLevel()) { }
~TwoCmdBuffersTest(void)2964 	virtual					~TwoCmdBuffersTest	(void) { }
2965 	virtual TestInstance*	createInstance		(Context&						context) const;
2966 	virtual void			checkSupport		(Context& context) const;
2967 protected:
2968 	VkCommandBufferLevel	m_cmdBufferLevel;
2969 };
2970 
2971 class TwoCmdBuffersTestInstance : public TimestampTestInstance
2972 {
2973 public:
2974 							TwoCmdBuffersTestInstance	(Context&				context,
2975 														 const StageFlagVector	stages,
2976 														 const bool				inRenderPass,
2977 														 const bool				hostQueryReset,
2978 														 const bool				transferOnlyQueue,
2979 														 VkCommandBufferLevel	cmdBufferLevel,
2980 														 VkQueryResultFlags		queryResultFlags);
2981 	virtual					~TwoCmdBuffersTestInstance	(void);
2982 	virtual tcu::TestStatus	iterate						(void);
2983 protected:
2984 	virtual void			configCommandBuffer			(void);
2985 
2986 protected:
2987 	Move<VkCommandBuffer>	m_secondCmdBuffer;
2988 	Move<VkBuffer>			m_dstBuffer;
2989 	de::MovePtr<Allocation> m_dstBufferAlloc;
2990 	VkCommandBufferLevel	m_cmdBufferLevel;
2991 };
2992 
createInstance(Context & context) const2993 TestInstance* TwoCmdBuffersTest::createInstance (Context& context) const
2994 {
2995 	return new TwoCmdBuffersTestInstance(context, m_stages, m_inRenderPass, m_hostQueryReset, m_transferOnlyQueue, m_cmdBufferLevel, m_queryResultFlags);
2996 }
2997 
checkSupport(Context & context) const2998 void TwoCmdBuffersTest::checkSupport(Context& context) const
2999 {
3000 	TimestampTest::checkSupport(context);
3001 #ifdef CTS_USES_VULKANSC
3002 	if (m_cmdBufferLevel == VK_COMMAND_BUFFER_LEVEL_SECONDARY && context.getDeviceVulkanSC10Properties().secondaryCommandBufferNullOrImagelessFramebuffer == VK_FALSE)
3003 		TCU_THROW(NotSupportedError, "secondaryCommandBufferNullFramebuffer is not supported");
3004 #endif
3005 }
3006 
TwoCmdBuffersTestInstance(Context & context,const StageFlagVector stages,const bool inRenderPass,const bool hostQueryReset,const bool transferOnlyQueue,VkCommandBufferLevel cmdBufferLevel,VkQueryResultFlags queryResultFlags)3007 TwoCmdBuffersTestInstance::TwoCmdBuffersTestInstance (Context&					context,
3008 													  const StageFlagVector		stages,
3009 													  const bool				inRenderPass,
3010 													  const bool				hostQueryReset,
3011 													  const bool				transferOnlyQueue,
3012 													  VkCommandBufferLevel		cmdBufferLevel,
3013 													  VkQueryResultFlags		queryResultFlags)
3014 : TimestampTestInstance (context, stages, inRenderPass, hostQueryReset, transferOnlyQueue, queryResultFlags), m_cmdBufferLevel(cmdBufferLevel)
3015 {
3016 	const DeviceInterface& vk = context.getDeviceInterface();
3017 
3018 	m_secondCmdBuffer	= allocateCommandBuffer(vk, m_device, *m_cmdPool, cmdBufferLevel);
3019 	m_dstBuffer			= createBufferAndBindMemory(1024, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, &m_dstBufferAlloc);
3020 }
3021 
~TwoCmdBuffersTestInstance(void)3022 TwoCmdBuffersTestInstance::~TwoCmdBuffersTestInstance (void)
3023 {
3024 }
3025 
configCommandBuffer(void)3026 void TwoCmdBuffersTestInstance::configCommandBuffer (void)
3027 {
3028 	const DeviceInterface& vk = m_context.getDeviceInterface();
3029 
3030 	const VkCommandBufferBeginInfo	cmdBufferBeginInfo	=
3031 	{
3032 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
3033 		DE_NULL,										// const void*                              pNext;
3034 		0u,												// VkCommandBufferUsageFlags                flags;
3035 		(const VkCommandBufferInheritanceInfo*)DE_NULL	// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
3036 	};
3037 
3038 	const vk::VkBufferMemoryBarrier bufferBarrier =
3039 	{
3040 		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
3041 		DE_NULL,										// const void*		pNext;
3042 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
3043 		vk::VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
3044 		VK_QUEUE_FAMILY_IGNORED,						// deUint32			srcQueueFamilyIndex;
3045 		VK_QUEUE_FAMILY_IGNORED,						// deUint32			dstQueueFamilyIndex;
3046 		*m_dstBuffer,									// VkBuffer			buffer;
3047 		0ull,											// VkDeviceSize		offset;
3048 		VK_WHOLE_SIZE									// VkDeviceSize		size;
3049 	};
3050 
3051 	if (m_cmdBufferLevel == VK_COMMAND_BUFFER_LEVEL_PRIMARY)
3052 	{
3053 		VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
3054 		if (!m_hostQueryReset)
3055 			vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
3056 		vk.cmdWriteTimestamp(*m_cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, *m_queryPool, 0);
3057 		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
3058 		VK_CHECK(vk.beginCommandBuffer(*m_secondCmdBuffer, &cmdBufferBeginInfo));
3059 		vk.cmdCopyQueryPoolResults(*m_secondCmdBuffer, *m_queryPool, 0u, 1u, *m_dstBuffer, 0u, 0u, m_queryResultFlags);
3060 		vk.cmdPipelineBarrier(*m_secondCmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u,
3061 							  0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
3062 		VK_CHECK(vk.endCommandBuffer(*m_secondCmdBuffer));
3063 	}
3064 	else
3065 	{
3066 		const VkCommandBufferInheritanceInfo inheritanceInfo		=
3067 		{
3068 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,	// VkStructureType                  sType;
3069 			DE_NULL,											// const void*                      pNext;
3070 			DE_NULL,											// VkRenderPass                     renderPass;
3071 			0u,													// deUint32                         subpass;
3072 			DE_NULL,											// VkFramebuffer                    framebuffer;
3073 			VK_FALSE,											// VkBool32                         occlusionQueryEnable;
3074 			0u,													// VkQueryControlFlags              queryFlags;
3075 			0u													// VkQueryPipelineStatisticFlags    pipelineStatistics;
3076 		};
3077 
3078 		const VkCommandBufferBeginInfo cmdBufferBeginInfoSecondary	=
3079 		{
3080 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,	// VkStructureType                          sType;
3081 			DE_NULL,										// const void*                              pNext;
3082 			0u,												// VkCommandBufferUsageFlags                flags;
3083 			&inheritanceInfo								// const VkCommandBufferInheritanceInfo*    pInheritanceInfo;
3084 		};
3085 
3086 		VK_CHECK(vk.beginCommandBuffer(*m_secondCmdBuffer, &cmdBufferBeginInfoSecondary));
3087 		if (!m_hostQueryReset)
3088 			vk.cmdResetQueryPool(*m_secondCmdBuffer, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
3089 		vk.cmdWriteTimestamp(*m_secondCmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, *m_queryPool, 0);
3090 		VK_CHECK(vk.endCommandBuffer(*m_secondCmdBuffer));
3091 		VK_CHECK(vk.beginCommandBuffer(*m_cmdBuffer, &cmdBufferBeginInfo));
3092 		vk.cmdExecuteCommands(m_cmdBuffer.get(), 1u, &m_secondCmdBuffer.get());
3093 		if (!m_transferOnlyQueue)
3094 			vk.cmdCopyQueryPoolResults(*m_cmdBuffer, *m_queryPool, 0u, 1u, *m_dstBuffer, 0u, 0u, m_queryResultFlags);
3095 		vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u,
3096 							  0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
3097 		VK_CHECK(vk.endCommandBuffer(*m_cmdBuffer));
3098 	}
3099 }
3100 
iterate(void)3101 tcu::TestStatus TwoCmdBuffersTestInstance::iterate (void)
3102 {
3103 	const DeviceInterface&		vk				= m_context.getDeviceInterface();
3104 	const VkQueue				queue			= getDeviceQueue(vk, m_device, m_queueFamilyIndex, 0);
3105 
3106 	configCommandBuffer();
3107 
3108 	const VkCommandBuffer		cmdBuffers[]	= { m_cmdBuffer.get(), m_secondCmdBuffer.get() };
3109 
3110 	const VkSubmitInfo			submitInfo		=
3111 	{
3112 		VK_STRUCTURE_TYPE_SUBMIT_INFO,									// VkStructureType                sType;
3113 		DE_NULL,														// const void*                    pNext;
3114 		0u,																// deUint32                       waitSemaphoreCount;
3115 		DE_NULL,														// const VkSemaphore*             pWaitSemaphores;
3116 		(const VkPipelineStageFlags*)DE_NULL,							// const VkPipelineStageFlags*    pWaitDstStageMask;
3117 		m_cmdBufferLevel == VK_COMMAND_BUFFER_LEVEL_PRIMARY ? 2u : 1u,	// deUint32                       commandBufferCount;
3118 		cmdBuffers,														// const VkCommandBuffer*         pCommandBuffers;
3119 		0u,																// deUint32                       signalSemaphoreCount;
3120 		DE_NULL,														// const VkSemaphore*             pSignalSemaphores;
3121 	};
3122 
3123 	if (m_hostQueryReset)
3124 	{
3125 		// Only reset the pool for the primary command buffer, the secondary command buffer will reset the pool by itself.
3126 		vk.resetQueryPool(m_device, *m_queryPool, 0u, TimestampTest::ENTRY_COUNT);
3127 	}
3128 
3129 	VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, DE_NULL));
3130 	VK_CHECK(vk.queueWaitIdle(queue));
3131 
3132 	// Always pass in case no crash occurred.
3133 	return tcu::TestStatus::pass("Pass");
3134 }
3135 
3136 class ConsistentQueryResultsTest : public vkt::TestCase
3137 {
3138 public:
ConsistentQueryResultsTest(tcu::TestContext & testContext,const std::string & name)3139 	ConsistentQueryResultsTest							(tcu::TestContext&	testContext,
3140 														 const std::string&	name)
3141 		: vkt::TestCase(testContext, name)
3142 		{ }
~ConsistentQueryResultsTest(void)3143 	virtual               ~ConsistentQueryResultsTest	(void) { }
3144 	virtual void          initPrograms					(SourceCollections&	programCollection) const;
3145 	virtual TestInstance* createInstance				(Context&			context) const;
3146 };
3147 
3148 class ConsistentQueryResultsTestInstance : public vkt::TestInstance
3149 {
3150 public:
3151 							ConsistentQueryResultsTestInstance	(Context& context);
~ConsistentQueryResultsTestInstance(void)3152 	virtual					~ConsistentQueryResultsTestInstance	(void) { }
3153 	virtual tcu::TestStatus	iterate								(void);
3154 protected:
3155 	Move<VkCommandPool>		m_cmdPool;
3156 	Move<VkCommandBuffer>	m_cmdBuffer;
3157 	Move<VkQueryPool>		m_queryPool;
3158 
3159 	deUint64				m_timestampMask;
3160 	Move<VkBuffer>			m_resultBuffer32Bits;
3161 	Move<VkBuffer>			m_resultBuffer64Bits;
3162 	de::MovePtr<Allocation>	m_resultBufferMemory32Bits;
3163 	de::MovePtr<Allocation>	m_resultBufferMemory64Bits;
3164 };
3165 
initPrograms(SourceCollections & programCollection) const3166 void ConsistentQueryResultsTest::initPrograms(SourceCollections& programCollection) const
3167 {
3168 	vkt::TestCase::initPrograms(programCollection);
3169 }
3170 
createInstance(Context & context) const3171 TestInstance* ConsistentQueryResultsTest::createInstance(Context& context) const
3172 {
3173 	return new ConsistentQueryResultsTestInstance(context);
3174 }
3175 
ConsistentQueryResultsTestInstance(Context & context)3176 ConsistentQueryResultsTestInstance::ConsistentQueryResultsTestInstance(Context& context)
3177 	: vkt::TestInstance(context)
3178 {
3179 	const DeviceInterface&	vk					= context.getDeviceInterface();
3180 	const VkDevice			vkDevice			= context.getDevice();
3181 	const deUint32			queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
3182 	Allocator&				allocator			= m_context.getDefaultAllocator();
3183 
3184 	// Check support for timestamp queries
3185 	m_timestampMask = checkTimestampsSupported(context.getInstanceInterface(), context.getPhysicalDevice(), queueFamilyIndex);
3186 
3187 	const VkQueryPoolCreateInfo queryPoolParams =
3188 	{
3189 		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,	// VkStructureType               sType;
3190 		DE_NULL,									// const void*                   pNext;
3191 		0u,											// VkQueryPoolCreateFlags        flags;
3192 		VK_QUERY_TYPE_TIMESTAMP,					// VkQueryType                   queryType;
3193 		1u,											// deUint32                      entryCount;
3194 		0u,											// VkQueryPipelineStatisticFlags pipelineStatistics;
3195 	};
3196 
3197 	m_queryPool		= createQueryPool(vk, vkDevice, &queryPoolParams);
3198 	m_cmdPool		= createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
3199 	m_cmdBuffer		= allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
3200 
3201 	// Create results buffer.
3202 	VkBufferCreateInfo bufferCreateInfo =
3203 	{
3204 		VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// VkStructureType		sType;
3205 		DE_NULL,									// const void*			pNext;
3206 		0u,											// VkBufferCreateFlags	flags;
3207 		0u,											// VkDeviceSize			size;
3208 		VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// VkBufferUsageFlags	usage;
3209 		VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode		sharingMode;
3210 		1u,											// deUint32				queueFamilyIndexCount;
3211 		&queueFamilyIndex							// const deUint32*		pQueueFamilyIndices;
3212 	};
3213 
3214 	// 32 bits.
3215 	bufferCreateInfo.size		= sizeof(deUint32);
3216 	m_resultBuffer32Bits		= createBuffer(vk, vkDevice, &bufferCreateInfo);
3217 	m_resultBufferMemory32Bits	= allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_resultBuffer32Bits), MemoryRequirement::HostVisible);
3218 	VK_CHECK(vk.bindBufferMemory(vkDevice, *m_resultBuffer32Bits, m_resultBufferMemory32Bits->getMemory(), m_resultBufferMemory32Bits->getOffset()));
3219 
3220 	// 64 bits.
3221 	bufferCreateInfo.size		= sizeof(deUint64);
3222 	m_resultBuffer64Bits		= createBuffer(vk, vkDevice, &bufferCreateInfo);
3223 	m_resultBufferMemory64Bits	= allocator.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_resultBuffer64Bits), MemoryRequirement::HostVisible);
3224 	VK_CHECK(vk.bindBufferMemory(vkDevice, *m_resultBuffer64Bits, m_resultBufferMemory64Bits->getMemory(), m_resultBufferMemory64Bits->getOffset()));
3225 
3226 	vk::VkBufferMemoryBarrier bufferBarrier =
3227 	{
3228 		vk::VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
3229 		DE_NULL,										// const void*		pNext;
3230 		vk::VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
3231 		vk::VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
3232 		VK_QUEUE_FAMILY_IGNORED,						// deUint32			srcQueueFamilyIndex;
3233 		VK_QUEUE_FAMILY_IGNORED,						// deUint32			dstQueueFamilyIndex;
3234 		DE_NULL,										// VkBuffer			buffer;
3235 		0ull,											// VkDeviceSize		offset;
3236 		VK_WHOLE_SIZE									// VkDeviceSize		size;
3237 	};
3238 
3239 	// Prepare command buffer.
3240 	beginCommandBuffer(vk, *m_cmdBuffer, 0u);
3241 	vk.cmdResetQueryPool(*m_cmdBuffer, *m_queryPool, 0u, 1u);
3242 	vk.cmdWriteTimestamp(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, *m_queryPool, 0u);
3243 
3244 	// 32 bits.
3245 	bufferBarrier.buffer = *m_resultBuffer32Bits;
3246 	vk.cmdCopyQueryPoolResults(*m_cmdBuffer, *m_queryPool, 0u, 1u, *m_resultBuffer32Bits, 0u, sizeof(deUint32), VK_QUERY_RESULT_WAIT_BIT);
3247 	vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
3248 
3249 	// 64 bits.
3250 	bufferBarrier.buffer = *m_resultBuffer64Bits;
3251 	vk.cmdCopyQueryPoolResults(*m_cmdBuffer, *m_queryPool, 0u, 1u, *m_resultBuffer64Bits, 0u, sizeof(deUint64), (VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
3252 	vk.cmdPipelineBarrier(*m_cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
3253 
3254 	endCommandBuffer(vk, *m_cmdBuffer);
3255 }
3256 
iterate(void)3257 tcu::TestStatus ConsistentQueryResultsTestInstance::iterate(void)
3258 {
3259 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
3260 	const VkDevice				vkDevice	= m_context.getDevice();
3261 	const VkQueue				queue		= m_context.getUniversalQueue();
3262 
3263 	deUint32					tsBuffer32Bits;
3264 	deUint64					tsBuffer64Bits;
3265 	deUint32					tsGet32Bits;
3266 	deUint64					tsGet64Bits;
3267 
3268 	constexpr deUint32			maxDeUint32Value = std::numeric_limits<deUint32>::max();
3269 
3270 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
3271 
3272 	// Get results from buffers.
3273 	invalidateAlloc(vk, vkDevice, *m_resultBufferMemory32Bits);
3274 	invalidateAlloc(vk, vkDevice, *m_resultBufferMemory64Bits);
3275 	deMemcpy(&tsBuffer32Bits, m_resultBufferMemory32Bits->getHostPtr(), sizeof(tsBuffer32Bits));
3276 	deMemcpy(&tsBuffer64Bits, m_resultBufferMemory64Bits->getHostPtr(), sizeof(tsBuffer64Bits));
3277 
3278 	// Get results with vkGetQueryPoolResults().
3279 	VK_CHECK(vk.getQueryPoolResults(vkDevice, *m_queryPool, 0u, 1u, sizeof(tsGet32Bits), &tsGet32Bits, sizeof(tsGet32Bits), VK_QUERY_RESULT_WAIT_BIT));
3280 	VK_CHECK(vk.getQueryPoolResults(vkDevice, *m_queryPool, 0u, 1u, sizeof(tsGet64Bits), &tsGet64Bits, sizeof(tsGet64Bits), (VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT)));
3281 
3282 	// Check timestamp mask for both 64-bit results.
3283 	checkTimestampBits(tsBuffer64Bits, m_timestampMask);
3284 	checkTimestampBits(tsGet64Bits, m_timestampMask);
3285 
3286 	// Check results are consistent.
3287 	if (tsBuffer32Bits == tsGet32Bits &&
3288 		tsBuffer64Bits == tsGet64Bits &&
3289 		(((tsGet64Bits & maxDeUint32Value) == tsGet32Bits) ||
3290 		((tsGet64Bits > maxDeUint32Value) && (maxDeUint32Value == tsGet32Bits))))
3291 	{
3292 		return tcu::TestStatus::pass("Pass");
3293 	}
3294 
3295 	std::ostringstream msg;
3296 	msg << std::hex << "Results are inconsistent:"
3297 		<< " B32=0x" << tsBuffer32Bits
3298 		<< " B64=0x" << tsBuffer64Bits
3299 		<< " G32=0x" << tsGet32Bits
3300 		<< " G64=0x" << tsGet64Bits;
3301 	return tcu::TestStatus::fail(msg.str());
3302 }
3303 
3304 } // anonymous
3305 
createTimestampTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)3306 tcu::TestCaseGroup* createTimestampTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
3307 {
3308 	de::MovePtr<tcu::TestCaseGroup> timestampTests (new tcu::TestCaseGroup(testCtx, "timestamp"));
3309 	const VkQueryResultFlags queryResultFlagsTimestampTest[] =
3310 	{
3311 		VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT,
3312 		VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT,
3313 	};
3314 
3315 	// Basic Graphics Tests
3316 	{
3317 		de::MovePtr<tcu::TestCaseGroup> basicGraphicsTests (new tcu::TestCaseGroup(testCtx, "basic_graphics_tests"));
3318 
3319 		const VkPipelineStageFlagBits basicGraphicsStages0[][2] =
3320 		{
3321 		  {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,   VK_PIPELINE_STAGE_VERTEX_INPUT_BIT},
3322 		  {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,   VK_PIPELINE_STAGE_VERTEX_SHADER_BIT},
3323 		  {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,   VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT},
3324 		  {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,   VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT},
3325 		  {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,   VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT},
3326 		  {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,   VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT},
3327 		  {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,   VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT},
3328 		  {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,   VK_PIPELINE_STAGE_ALL_COMMANDS_BIT},
3329 		};
3330 		for (deUint32 stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(basicGraphicsStages0); stageNdx++)
3331 		{
3332 			for (deUint32 flagsIdx = 0u; flagsIdx < DE_LENGTH_OF_ARRAY(queryResultFlagsTimestampTest); flagsIdx++)
3333 			{
3334 				TimestampTestParam param(pipelineConstructionType, basicGraphicsStages0[stageNdx], 2u, true, false, false, queryResultFlagsTimestampTest[flagsIdx]);
3335 				basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, &param));
3336 				param.toggleInRenderPass();
3337 				basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, &param));
3338 				// Host Query reset tests
3339 				param.toggleHostQueryReset();
3340 				basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, &param));
3341 				param.toggleInRenderPass();
3342 				basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, &param));
3343 			}
3344 		}
3345 
3346 		const VkPipelineStageFlagBits basicGraphicsStages1[][3] =
3347 		{
3348 		  {VK_PIPELINE_STAGE_VERTEX_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,      VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT},
3349 		  {VK_PIPELINE_STAGE_VERTEX_INPUT_BIT,  VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT},
3350 		};
3351 		for (deUint32 stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(basicGraphicsStages1); stageNdx++)
3352 		{
3353 			for (deUint32 flagsIdx = 0u; flagsIdx < DE_LENGTH_OF_ARRAY(queryResultFlagsTimestampTest); flagsIdx++)
3354 			{
3355 				TimestampTestParam param(pipelineConstructionType, basicGraphicsStages1[stageNdx], 3u, true, false, false, queryResultFlagsTimestampTest[flagsIdx]);
3356 				basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, &param));
3357 				param.toggleInRenderPass();
3358 				basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, &param));
3359 				// Host Query reset tests
3360 				param.toggleHostQueryReset();
3361 				basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, &param));
3362 				param.toggleInRenderPass();
3363 				basicGraphicsTests->addChild(newTestCase<BasicGraphicsTest>(testCtx, &param));
3364 			}
3365 		}
3366 
3367 		timestampTests->addChild(basicGraphicsTests.release());
3368 	}
3369 
3370 	// Advanced Graphics Tests
3371 	{
3372 		// Record timestamp in different pipeline stages of advanced graphics tests
3373 		de::MovePtr<tcu::TestCaseGroup> advGraphicsTests (new tcu::TestCaseGroup(testCtx, "advanced_graphics_tests"));
3374 
3375 		const VkPipelineStageFlagBits advGraphicsStages[][2] =
3376 		{
3377 			{VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT},
3378 			{VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT},
3379 			{VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT},
3380 			{VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT},
3381 		};
3382 		for (deUint32 stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(advGraphicsStages); stageNdx++)
3383 		{
3384 			for (deUint32 flagsIdx = 0u; flagsIdx < DE_LENGTH_OF_ARRAY(queryResultFlagsTimestampTest); flagsIdx++)
3385 			{
3386 				TimestampTestParam param(pipelineConstructionType, advGraphicsStages[stageNdx], 2u, true, false, false, queryResultFlagsTimestampTest[flagsIdx]);
3387 				advGraphicsTests->addChild(newTestCase<AdvGraphicsTest>(testCtx, &param));
3388 				param.toggleInRenderPass();
3389 				advGraphicsTests->addChild(newTestCase<AdvGraphicsTest>(testCtx, &param));
3390 				// Host Query reset tests
3391 				param.toggleHostQueryReset();
3392 				advGraphicsTests->addChild(newTestCase<AdvGraphicsTest>(testCtx, &param));
3393 				param.toggleInRenderPass();
3394 				advGraphicsTests->addChild(newTestCase<AdvGraphicsTest>(testCtx, &param));
3395 			}
3396 		}
3397 
3398 		timestampTests->addChild(advGraphicsTests.release());
3399 	}
3400 
3401 	// Basic Compute Tests - don't repeat those tests for graphics pipeline library
3402 	if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3403 	{
3404 		de::MovePtr<tcu::TestCaseGroup> basicComputeTests (new tcu::TestCaseGroup(testCtx, "basic_compute_tests", "Record timestamp for compute stages"));
3405 
3406 		const VkPipelineStageFlagBits basicComputeStages[][2] =
3407 		{
3408 			{VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT},
3409 			{VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT},
3410 		};
3411 		for (deUint32 stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(basicComputeStages); stageNdx++)
3412 		{
3413 			for (deUint32 flagsIdx = 0u; flagsIdx < DE_LENGTH_OF_ARRAY(queryResultFlagsTimestampTest); flagsIdx++)
3414 			{
3415 				TimestampTestParam param(pipelineConstructionType, basicComputeStages[stageNdx], 2u, false, false, false, queryResultFlagsTimestampTest[flagsIdx]);
3416 				basicComputeTests->addChild(newTestCase<BasicComputeTest>(testCtx, &param));
3417 				// Host Query reset test
3418 				param.toggleHostQueryReset();
3419 				basicComputeTests->addChild(newTestCase<BasicComputeTest>(testCtx, &param));
3420 			}
3421 		}
3422 
3423 		timestampTests->addChild(basicComputeTests.release());
3424 	}
3425 
3426 	// Transfer Tests - don't repeat those tests for graphics pipeline library
3427 	if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3428 	{
3429 		de::MovePtr<tcu::TestCaseGroup> transferTests (new tcu::TestCaseGroup(testCtx, "transfer_tests", "Record timestamp for transfer stages"));
3430 
3431 		const VkPipelineStageFlagBits transferStages[][2] =
3432 		{
3433 			{VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT},
3434 			{VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_HOST_BIT},
3435 		};
3436 
3437 		for (deUint32 transferOnlyQueue = 0u; transferOnlyQueue < 2; transferOnlyQueue++)
3438 		{
3439 			for (deUint32 stageNdx = 0u; stageNdx < DE_LENGTH_OF_ARRAY(transferStages); stageNdx++)
3440 			{
3441 				for (deUint32 method = 0u; method < TRANSFER_METHOD_LAST; method++)
3442 				{
3443 					if (transferOnlyQueue)
3444 					{
3445 						// skip tests that use commands not supported on transfer only queue
3446 						if (method == TRANSFER_METHOD_BLIT_IMAGE ||
3447 							method == TRANSFER_METHOD_CLEAR_COLOR_IMAGE ||
3448 							method == TRANSFER_METHOD_CLEAR_DEPTH_STENCIL_IMAGE ||
3449 							method == TRANSFER_METHOD_RESOLVE_IMAGE ||
3450 							method == TRANSFER_METHOD_COPY_QUERY_POOL_RESULTS ||
3451 							method == TRANSFER_METHOD_COPY_QUERY_POOL_RESULTS_STRIDE_ZERO)
3452 							continue;
3453 					}
3454 
3455 					for (deUint32 flagsIdx = 0u; flagsIdx < DE_LENGTH_OF_ARRAY(queryResultFlagsTimestampTest); flagsIdx++)
3456 					{
3457 						TransferTimestampTestParam param(pipelineConstructionType, transferStages[stageNdx], 2u, false, false, transferOnlyQueue, method, queryResultFlagsTimestampTest[flagsIdx]);
3458 
3459 						// execute tests that use cmdResetQueryPool only on default device
3460 						if (!transferOnlyQueue)
3461 							transferTests->addChild(newTestCase<TransferTest>(testCtx, &param));
3462 
3463 						// Host Query reset test
3464 						param.toggleHostQueryReset();
3465 						transferTests->addChild(newTestCase<TransferTest>(testCtx, &param));
3466 					}
3467 				}
3468 			}
3469 		}
3470 
3471 		timestampTests->addChild(transferTests.release());
3472 	}
3473 
3474 	// Calibrated Timestamp Tests - don't repeat those tests for graphics pipeline library
3475 	if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3476 	{
3477 		de::MovePtr<tcu::TestCaseGroup> calibratedTimestampTests (new tcu::TestCaseGroup(testCtx, "calibrated", "VK_EXT_calibrated_timestamps tests"));
3478 
3479 		calibratedTimestampTests->addChild(new CalibratedTimestampTest<CalibratedTimestampDevDomainTestInstance>	(testCtx, "dev_domain_test"));
3480 		calibratedTimestampTests->addChild(new CalibratedTimestampTest<CalibratedTimestampHostDomainTestInstance>	(testCtx, "host_domain_test"));
3481 		// Test calibration using device and host domains
3482 		calibratedTimestampTests->addChild(new CalibratedTimestampTest<CalibratedTimestampCalibrationTestInstance>	(testCtx, "calibration_test"));
3483 
3484 		timestampTests->addChild(calibratedTimestampTests.release());
3485 	}
3486 
3487 	// Misc Tests - don't repeat those tests for graphics pipeline library
3488 	if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
3489 	{
3490 		const VkQueryResultFlags queryResultFlagsMiscTests[] =
3491 		{
3492 			VK_QUERY_RESULT_WAIT_BIT,
3493 			VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT,
3494 		};
3495 
3496 		const std::string queryResultsFlagsMiscTestsStr[] = {"", "_with_availability_bit"};
3497 
3498 		de::MovePtr<tcu::TestCaseGroup> miscTests (new tcu::TestCaseGroup(testCtx, "misc_tests", "Misc tests that can not be categorized to other group."));
3499 
3500 		for (deUint32 flagsIdx = 0u; flagsIdx < DE_LENGTH_OF_ARRAY(queryResultFlagsMiscTests); flagsIdx++)
3501 		{
3502 			const VkPipelineStageFlagBits miscStages[] = {VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT};
3503 			TimestampTestParam param(pipelineConstructionType, miscStages, 1u, false, false, false, queryResultFlagsTimestampTest[flagsIdx]);
3504 			// Only write timestamp command in the commmand buffer
3505 			miscTests->addChild(new TimestampTest(testCtx,
3506 												"timestamp_only" + queryResultsFlagsMiscTestsStr[flagsIdx], &param));
3507 
3508 			TwoCmdBuffersTestParam twoCmdBuffersParamPrimary(pipelineConstructionType, miscStages, 1u, false, false, false, VK_COMMAND_BUFFER_LEVEL_PRIMARY, queryResultFlagsMiscTests[flagsIdx]);
3509 			// Issue query in a command buffer and copy it on another primary command buffer
3510 			miscTests->addChild(new TwoCmdBuffersTest(testCtx,
3511 													"two_cmd_buffers_primary" + queryResultsFlagsMiscTestsStr[flagsIdx], &twoCmdBuffersParamPrimary));
3512 
3513 			TwoCmdBuffersTestParam twoCmdBuffersParamSecondary(pipelineConstructionType, miscStages, 1u, false, false, false, VK_COMMAND_BUFFER_LEVEL_SECONDARY, queryResultFlagsMiscTests[flagsIdx]);
3514 			// Issue query in a secondary command buffer and copy it on a primary command buffer
3515 			miscTests->addChild(new TwoCmdBuffersTest(testCtx,
3516 													"two_cmd_buffers_secondary" + queryResultsFlagsMiscTestsStr[flagsIdx], &twoCmdBuffersParamSecondary));
3517 			// Misc: Host Query Reset tests
3518 			param.toggleHostQueryReset();
3519 			// Only write timestamp command in the commmand buffer
3520 			miscTests->addChild(new TimestampTest(testCtx,
3521 												"timestamp_only_host_query_reset" + queryResultsFlagsMiscTestsStr[flagsIdx], &param));
3522 			TwoCmdBuffersTestParam twoCmdBuffersParamPrimaryHostQueryReset(pipelineConstructionType, miscStages, 1u, false, true, false, VK_COMMAND_BUFFER_LEVEL_PRIMARY, queryResultFlagsMiscTests[flagsIdx]);
3523 			// Issue query in a command buffer and copy it on another primary command buffer
3524 			miscTests->addChild(new TwoCmdBuffersTest(testCtx,
3525 													"two_cmd_buffers_primary_host_query_reset" + queryResultsFlagsMiscTestsStr[flagsIdx], &twoCmdBuffersParamPrimaryHostQueryReset));
3526 
3527 			TwoCmdBuffersTestParam twoCmdBuffersParamSecondaryHostQueryReset(pipelineConstructionType, miscStages, 1u, false, true, false, VK_COMMAND_BUFFER_LEVEL_SECONDARY, queryResultFlagsMiscTests[flagsIdx]);
3528 			// Issue query in a secondary command buffer and copy it on a primary command buffer
3529 			miscTests->addChild(new TwoCmdBuffersTest(testCtx,
3530 													"two_cmd_buffers_secondary_host_query_reset" + queryResultsFlagsMiscTestsStr[flagsIdx], &twoCmdBuffersParamSecondaryHostQueryReset));
3531 			TwoCmdBuffersTestParam twoCmdBuffersParamSecondaryTransferQueue(pipelineConstructionType, miscStages, 1u, false, true, true, VK_COMMAND_BUFFER_LEVEL_SECONDARY, queryResultFlagsMiscTests[flagsIdx]);
3532 			// Issue query in a secondary command buffer and copy it on a primary command buffer
3533 			miscTests->addChild(new TwoCmdBuffersTest(testCtx,
3534 													"two_cmd_buffers_secondary_transfer_queue" + queryResultsFlagsMiscTestsStr[flagsIdx], &twoCmdBuffersParamSecondaryTransferQueue));
3535 		}
3536 		// Reset timestamp query before copying results.
3537 		miscTests->addChild(new ResetTimestampQueryBeforeCopyTest(testCtx, "reset_query_before_copy"));
3538 
3539 		// Fill buffer with 0s before copying results.
3540 		miscTests->addChild(new FillBufferBeforeCopyTest(testCtx, "fill_buffer_before_copy"));
3541 
3542 
3543 		// Check consistency between 32 and 64 bits.
3544 		miscTests->addChild(new ConsistentQueryResultsTest(testCtx, "consistent_results"));
3545 
3546 		timestampTests->addChild(miscTests.release());
3547 	}
3548 
3549 	return timestampTests.release();
3550 }
3551 
3552 } // pipeline
3553 
3554 } // vkt
3555