• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2020 The Khronos Group Inc.
6  * Copyright (c) 2020 Valve Corporation
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Vulkan Concurrent Query Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktQueryPoolConcurrentTests.hpp"
26 
27 #include "vktTestCase.hpp"
28 
29 #include "vktDrawImageObjectUtil.hpp"
30 #include "vktDrawBufferObjectUtil.hpp"
31 #include "vktDrawCreateInfoUtil.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkRef.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkQueryUtil.hpp"
38 
39 #include "tcuTestLog.hpp"
40 #include "tcuImageCompare.hpp"
41 
42 #include <memory>
43 
44 namespace vkt
45 {
46 
47 namespace QueryPool
48 {
49 
50 using namespace Draw;
51 
52 namespace
53 {
54 
55 enum QueryType
56 {
57 	QUERY_TYPE_OCCLUSION = vk::VK_QUERY_TYPE_OCCLUSION,
58 	QUERY_TYPE_PIPELINE_STATISTICS = vk::VK_QUERY_TYPE_PIPELINE_STATISTICS,
59 	QUERY_TYPE_TIMESTAMP = vk::VK_QUERY_TYPE_TIMESTAMP,
60 	NUM_QUERY_POOLS = 3
61 };
62 
63 struct StateObjects
64 {
65 			StateObjects	(const vk::DeviceInterface&vk, vkt::Context &context, const int numVertices, vk::VkPrimitiveTopology primitive);
66 	void	setVertices		(const vk::DeviceInterface&vk, std::vector<tcu::Vec4> vertices);
67 
68 	enum
69 	{
70 		WIDTH	= 128,
71 		HEIGHT	= 128
72 	};
73 
74 	vkt::Context &m_context;
75 
76 	vk::Move<vk::VkPipeline>		m_pipeline;
77 	vk::Move<vk::VkPipelineLayout>	m_pipelineLayout;
78 
79 	de::SharedPtr<Image>			m_colorAttachmentImage, m_DepthImage;
80 	vk::Move<vk::VkImageView>		m_attachmentView;
81 	vk::Move<vk::VkImageView>		m_depthiew;
82 
83 	vk::Move<vk::VkRenderPass>		m_renderPass;
84 	vk::Move<vk::VkFramebuffer>		m_framebuffer;
85 
86 	de::SharedPtr<Buffer>			m_vertexBuffer;
87 
88 	vk::VkFormat					m_colorAttachmentFormat;
89 };
90 
StateObjects(const vk::DeviceInterface & vk,vkt::Context & context,const int numVertices,vk::VkPrimitiveTopology primitive)91 StateObjects::StateObjects (const vk::DeviceInterface&vk, vkt::Context &context, const int numVertices, vk::VkPrimitiveTopology primitive)
92 	: m_context(context)
93 	, m_colorAttachmentFormat(vk::VK_FORMAT_R8G8B8A8_UNORM)
94 
95 {
96 	vk::VkFormat		depthFormat = vk::VK_FORMAT_D16_UNORM;
97 	const vk::VkDevice	device		= m_context.getDevice();
98 
99 	//attachment images and views
100 	{
101 		vk::VkExtent3D imageExtent =
102 		{
103 			WIDTH,	// width;
104 			HEIGHT,	// height;
105 			1		// depth;
106 		};
107 
108 		const ImageCreateInfo colorImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, imageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL,
109 												   vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
110 
111 		m_colorAttachmentImage	= Image::createAndAlloc(vk, device, colorImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
112 
113 		const ImageViewCreateInfo attachmentViewInfo(m_colorAttachmentImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
114 		m_attachmentView		= vk::createImageView(vk, device, &attachmentViewInfo);
115 
116 		ImageCreateInfo depthImageCreateInfo(vk::VK_IMAGE_TYPE_2D, depthFormat, imageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL,
117 			vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
118 
119 		m_DepthImage			= Image::createAndAlloc(vk, device, depthImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
120 
121 		// Construct a depth  view from depth image
122 		const ImageViewCreateInfo depthViewInfo(m_DepthImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, depthFormat);
123 		m_depthiew				= vk::createImageView(vk, device, &depthViewInfo);
124 	}
125 
126 	{
127 		// Renderpass and Framebuffer
128 
129 		RenderPassCreateInfo renderPassCreateInfo;
130 		renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,									// format
131 																	vk::VK_SAMPLE_COUNT_1_BIT,								// samples
132 																	vk::VK_ATTACHMENT_LOAD_OP_CLEAR,						// loadOp
133 																	vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,					// storeOp
134 																	vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// stencilLoadOp
135 																	vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,					// stencilLoadOp
136 																	vk::VK_IMAGE_LAYOUT_GENERAL,							// initialLauout
137 																	vk::VK_IMAGE_LAYOUT_GENERAL));							// finalLayout
138 
139 		renderPassCreateInfo.addAttachment(AttachmentDescription(depthFormat,												// format
140 																 vk::VK_SAMPLE_COUNT_1_BIT,									// samples
141 																 vk::VK_ATTACHMENT_LOAD_OP_CLEAR,							// loadOp
142 																 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,						// storeOp
143 																 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,						// stencilLoadOp
144 																 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,						// stencilLoadOp
145 																 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,		// initialLauout
146 																 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));	// finalLayout
147 
148 		const vk::VkAttachmentReference colorAttachmentReference =
149 		{
150 			0,															// attachment
151 			vk::VK_IMAGE_LAYOUT_GENERAL									// layout
152 		};
153 
154 		const vk::VkAttachmentReference depthAttachmentReference =
155 		{
156 			1,															// attachment
157 			vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL		// layout
158 		};
159 
160 		renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS,					// pipelineBindPoint
161 														   0,													// flags
162 														   0,													// inputCount
163 														   DE_NULL,												// pInputAttachments
164 														   1,													// colorCount
165 														   &colorAttachmentReference,							// pColorAttachments
166 														   DE_NULL,												// pResolveAttachments
167 														   depthAttachmentReference,							// depthStencilAttachment
168 														   0,													// preserveCount
169 														   DE_NULL));											// preserveAttachments
170 
171 		m_renderPass = vk::createRenderPass(vk, device, &renderPassCreateInfo);
172 
173 		std::vector<vk::VkImageView> attachments(2);
174 		attachments[0] = *m_attachmentView;
175 		attachments[1] = *m_depthiew;
176 
177 		FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, attachments, WIDTH, HEIGHT, 1);
178 		m_framebuffer = vk::createFramebuffer(vk, device, &framebufferCreateInfo);
179 	}
180 
181 	{
182 		// Pipeline
183 
184 		vk::Unique<vk::VkShaderModule> vs(vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
185 		vk::Unique<vk::VkShaderModule> fs(vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
186 
187 		const PipelineCreateInfo::ColorBlendState::Attachment attachmentState;
188 
189 		const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
190 		m_pipelineLayout = vk::createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
191 
192 		const vk::VkVertexInputBindingDescription vf_binding_desc		=
193 		{
194 			0,																// binding;
195 			4 * (deUint32)sizeof(float),									// stride;
196 			vk::VK_VERTEX_INPUT_RATE_VERTEX									// inputRate
197 		};
198 
199 		const vk::VkVertexInputAttributeDescription vf_attribute_desc	=
200 		{
201 			0,																// location;
202 			0,																// binding;
203 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,								// format;
204 			0																// offset;
205 		};
206 
207 		const vk::VkPipelineVertexInputStateCreateInfo vf_info			=
208 		{																	// sType;
209 			vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// pNext;
210 			NULL,															// flags;
211 			0u,																// vertexBindingDescriptionCount;
212 			1,																// pVertexBindingDescriptions;
213 			&vf_binding_desc,												// vertexAttributeDescriptionCount;
214 			1,																// pVertexAttributeDescriptions;
215 			&vf_attribute_desc
216 		};
217 
218 		PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
219 		pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
220 		pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
221 		pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(primitive));
222 		pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &attachmentState));
223 		const vk::VkViewport viewport	= vk::makeViewport(WIDTH, HEIGHT);
224 		const vk::VkRect2D scissor		= vk::makeRect2D(WIDTH, HEIGHT);
225 		pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport), std::vector<vk::VkRect2D>(1, scissor)));
226 		pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState(true, true, vk::VK_COMPARE_OP_GREATER_OR_EQUAL));
227 		pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
228 		pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
229 		pipelineCreateInfo.addState(vf_info);
230 		m_pipeline = vk::createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
231 	}
232 
233 	{
234 		// Vertex buffer
235 		const size_t kBufferSize = numVertices * sizeof(tcu::Vec4);
236 		m_vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(kBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
237 	}
238 }
239 
setVertices(const vk::DeviceInterface & vk,std::vector<tcu::Vec4> vertices)240 void StateObjects::setVertices (const vk::DeviceInterface&vk, std::vector<tcu::Vec4> vertices)
241 {
242 	const vk::VkDevice device			= m_context.getDevice();
243 
244 	tcu::Vec4 *ptr = reinterpret_cast<tcu::Vec4*>(m_vertexBuffer->getBoundMemory().getHostPtr());
245 	std::copy(vertices.begin(), vertices.end(), ptr);
246 
247 	vk::flushAlloc(vk, device,	m_vertexBuffer->getBoundMemory());
248 }
249 
250 class PrimaryCommandBufferConcurrentTestInstance : public vkt::TestInstance
251 {
252 public:
253 	PrimaryCommandBufferConcurrentTestInstance		(vkt::Context &context);
254 	~PrimaryCommandBufferConcurrentTestInstance		(void);
255 private:
256 	tcu::TestStatus					iterate							(void);
257 
258 	enum
259 	{
260 		NUM_QUERIES_IN_POOL				= 2,
261 		QUERY_INDEX_CAPTURE_EMPTY		= 0,
262 		QUERY_INDEX_CAPTURE_DRAWCALL	= 1,
263 		NUM_VERTICES_IN_DRAWCALL		= 3
264 	};
265 
266 	std::unique_ptr<StateObjects>		m_stateObjects;
267 	vk::Move<vk::VkQueryPool>			m_queryPools[NUM_QUERY_POOLS];
268 	deBool								m_supportedQueryType[NUM_QUERY_POOLS];
269 };
270 
PrimaryCommandBufferConcurrentTestInstance(vkt::Context & context)271 PrimaryCommandBufferConcurrentTestInstance::PrimaryCommandBufferConcurrentTestInstance (vkt::Context &context)
272 	: TestInstance		(context)
273 {
274 	// Check support for multiple query types
275 	{
276 		for(deUint32 poolNdx = 0; poolNdx < NUM_QUERY_POOLS; poolNdx++)
277 			m_supportedQueryType[poolNdx] = DE_FALSE;
278 
279 		deUint32 numSupportedQueryTypes = 0;
280 		m_supportedQueryType[QUERY_TYPE_OCCLUSION] = DE_TRUE;
281 		numSupportedQueryTypes++;
282 
283 		if (context.getDeviceFeatures().pipelineStatisticsQuery)
284 		{
285 			m_supportedQueryType[QUERY_TYPE_PIPELINE_STATISTICS] = DE_TRUE;
286 			numSupportedQueryTypes++;
287 		}
288 
289 		// Check support for timestamp queries
290 		{
291 			const deUint32									queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
292 			const std::vector<vk::VkQueueFamilyProperties>	queueProperties		= vk::getPhysicalDeviceQueueFamilyProperties(context.getInstanceInterface(), context.getPhysicalDevice());
293 
294 			DE_ASSERT(queueFamilyIndex < (deUint32)queueProperties.size());
295 
296 			if (queueProperties[queueFamilyIndex].timestampValidBits)
297 			 {
298 				 m_supportedQueryType[QUERY_TYPE_TIMESTAMP] = DE_TRUE;
299 				 numSupportedQueryTypes++;
300 			 }
301 		}
302 		if (numSupportedQueryTypes < 2)
303 			throw tcu::NotSupportedError("Device does not support multiple query types");
304 	}
305 
306 	m_stateObjects = std::unique_ptr<StateObjects>(new StateObjects(m_context.getDeviceInterface(), m_context, NUM_VERTICES_IN_DRAWCALL, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
307 
308 	const vk::VkDevice			device	= m_context.getDevice();
309 	const vk::DeviceInterface&	vk		= m_context.getDeviceInterface();
310 
311 	for(deUint32 poolNdx = 0; poolNdx < NUM_QUERY_POOLS; poolNdx++)
312 	{
313 		if (!m_supportedQueryType[poolNdx])
314 			continue;
315 
316 		vk::VkQueryPoolCreateInfo queryPoolCreateInfo =
317 		{
318 			vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
319 			DE_NULL,
320 			0u,
321 			static_cast<vk::VkQueryType>(poolNdx),
322 			NUM_QUERIES_IN_POOL,
323 			0u,
324 		};
325 		if (poolNdx == QUERY_TYPE_PIPELINE_STATISTICS)
326 			queryPoolCreateInfo.pipelineStatistics = vk::VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT;
327 
328 		m_queryPools[poolNdx] = createQueryPool(vk, device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL);
329 	}
330 
331 	std::vector<tcu::Vec4> vertices(NUM_VERTICES_IN_DRAWCALL);
332 	vertices[0] = tcu::Vec4(0.5, 0.5, 0.0, 1.0);
333 	vertices[1] = tcu::Vec4(0.5, 0.0, 0.0, 1.0);
334 	vertices[2] = tcu::Vec4(0.0, 0.5, 0.0, 1.0);
335 	m_stateObjects->setVertices(vk, vertices);
336 }
337 
~PrimaryCommandBufferConcurrentTestInstance(void)338 PrimaryCommandBufferConcurrentTestInstance::~PrimaryCommandBufferConcurrentTestInstance (void)
339 {
340 }
341 
iterate(void)342 tcu::TestStatus	PrimaryCommandBufferConcurrentTestInstance::iterate (void)
343 {
344 	tcu::TestLog &log				= m_context.getTestContext().getLog();
345 	const vk::VkDevice device		= m_context.getDevice();
346 	const vk::VkQueue queue			= m_context.getUniversalQueue();
347 	const vk::DeviceInterface& vk	= m_context.getDeviceInterface();
348 
349 	const CmdPoolCreateInfo			cmdPoolCreateInfo	(m_context.getUniversalQueueFamilyIndex());
350 	vk::Move<vk::VkCommandPool>		cmdPool				= vk::createCommandPool(vk, device, &cmdPoolCreateInfo);
351 
352 	vk::Unique<vk::VkCommandBuffer> cmdBuffer			(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
353 
354 	beginCommandBuffer(vk, *cmdBuffer);
355 
356 	initialTransitionColor2DImage(vk, *cmdBuffer, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
357 								  vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
358 	initialTransitionDepth2DImage(vk, *cmdBuffer, m_stateObjects->m_DepthImage->object(), vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
359 								  vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
360 
361 	std::vector<vk::VkClearValue> renderPassClearValues(2);
362 	deMemset(&renderPassClearValues[0], 0, static_cast<int>(renderPassClearValues.size()) * sizeof(vk::VkClearValue));
363 
364 	for (deUint32 poolNdx = 0u; poolNdx < NUM_QUERY_POOLS; poolNdx++)
365 	{
366 		if (m_supportedQueryType[poolNdx])
367 			vk.cmdResetQueryPool(*cmdBuffer, *m_queryPools[poolNdx], 0u, NUM_QUERIES_IN_POOL);
368 	}
369 
370 	beginRenderPass(vk, *cmdBuffer, *m_stateObjects->m_renderPass, *m_stateObjects->m_framebuffer, vk::makeRect2D(0, 0, StateObjects::WIDTH, StateObjects::HEIGHT), (deUint32)renderPassClearValues.size(), &renderPassClearValues[0]);
371 
372 	vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stateObjects->m_pipeline);
373 
374 	vk::VkBuffer vertexBuffer = m_stateObjects->m_vertexBuffer->object();
375 	const vk::VkDeviceSize vertexBufferOffset = 0;
376 	vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
377 
378 	// Begin all queries
379 	for (deUint32 poolNdx = 0u; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++)
380 	{
381 		if (m_supportedQueryType[poolNdx])
382 			vk.cmdBeginQuery(*cmdBuffer, *m_queryPools[poolNdx], QUERY_INDEX_CAPTURE_EMPTY, 0u);
383 	}
384 
385 	// End first capture (should not have any result). Start the second one.
386 	for (deUint32 poolNdx = 0u; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++)
387 	{
388 		if (m_supportedQueryType[poolNdx])
389 		{
390 			vk.cmdEndQuery(*cmdBuffer, *m_queryPools[poolNdx],	QUERY_INDEX_CAPTURE_EMPTY);
391 			vk.cmdBeginQuery(*cmdBuffer, *m_queryPools[poolNdx], QUERY_INDEX_CAPTURE_DRAWCALL, 0u);
392 		}
393 	}
394 
395 	vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, 0, 0);
396 
397 	if (m_supportedQueryType[QUERY_TYPE_TIMESTAMP])
398 		vk.cmdWriteTimestamp(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, *m_queryPools[QUERY_TYPE_TIMESTAMP], QUERY_INDEX_CAPTURE_DRAWCALL);
399 
400 	for (deUint32 poolNdx = 0u; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++)
401 	{
402 		if (m_supportedQueryType[poolNdx])
403 			vk.cmdEndQuery(*cmdBuffer, *m_queryPools[poolNdx],	QUERY_INDEX_CAPTURE_DRAWCALL);
404 	}
405 
406 	endRenderPass(vk, *cmdBuffer);
407 
408 	transition2DImage(vk, *cmdBuffer, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT,
409 					  vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
410 					  vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
411 
412 	endCommandBuffer(vk, *cmdBuffer);
413 
414 	submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
415 
416 	deUint64 queryResults[NUM_QUERIES_IN_POOL] = { 0 };
417 	size_t queryResultsSize		= sizeof(queryResults);
418 	bool passed = true;
419 
420 	// Occlusion and pipeline statistics queries verification
421 	for (deUint32 poolNdx = 0; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++)
422 	{
423 		if (m_supportedQueryType[poolNdx] == DE_FALSE)
424 			continue;
425 		vk::VkResult queryResult	= vk.getQueryPoolResults(device, *m_queryPools[poolNdx], 0, NUM_QUERIES_IN_POOL, queryResultsSize, queryResults, sizeof(queryResults[0]), vk::VK_QUERY_RESULT_64_BIT);
426 
427 		if (queryResult == vk::VK_NOT_READY)
428 		{
429 			TCU_FAIL("Query result not available, but vkWaitIdle() was called.");
430 		}
431 
432 		VK_CHECK(queryResult);
433 		std::string name = (poolNdx == QUERY_TYPE_OCCLUSION) ? "OcclusionQueryResults" : "PipelineStatisticsQueryResults";
434 		std::string desc = (poolNdx == QUERY_TYPE_OCCLUSION) ? "Occlusion query results" : "PipelineStatistics query results";
435 		log << tcu::TestLog::Section(name, desc);
436 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(queryResults); ++ndx)
437 		{
438 			log << tcu::TestLog::Message << "query[slot == " << ndx
439 				<< "] result == " << queryResults[ndx] << tcu::TestLog::EndMessage;
440 		}
441 
442 
443 		for (deUint32 queryNdx = 0; queryNdx < DE_LENGTH_OF_ARRAY(queryResults); ++queryNdx)
444 		{
445 			if (queryNdx == QUERY_INDEX_CAPTURE_EMPTY && queryResults[queryNdx] != 0u)
446 			{
447 				log << tcu::TestLog::Message << "vkGetQueryPoolResults returned "
448 					"wrong value of query for index "
449 					<< queryNdx << ", expected any zero value, got "
450 					<< queryResults[0] << "." << tcu::TestLog::EndMessage;
451 				passed = false;
452 			}
453 
454 			if (queryNdx != QUERY_INDEX_CAPTURE_EMPTY && queryResults[queryNdx] == 0)
455 			{
456 				log << tcu::TestLog::Message << "vkGetQueryPoolResults returned "
457 					"wrong value of query for index "
458 					<< queryNdx << ", expected any non-zero value, got "
459 					<< queryResults[0] << "." << tcu::TestLog::EndMessage;
460 				passed = false;
461 			}
462 		}
463 		log << tcu::TestLog::EndSection;
464 	}
465 
466 	// Timestamp query verification
467 	if (m_supportedQueryType[QUERY_TYPE_TIMESTAMP])
468 	{
469 		std::pair<deUint64, deUint64>	queryResultsWithAvailabilityBit[NUM_QUERIES_IN_POOL];
470 		size_t queryResultsWithAvailabilityBitSize		= sizeof(queryResultsWithAvailabilityBit);
471 		vk::VkResult queryResult	= vk.getQueryPoolResults(device, *m_queryPools[QUERY_TYPE_TIMESTAMP], 0, NUM_QUERIES_IN_POOL, queryResultsWithAvailabilityBitSize, &queryResultsWithAvailabilityBit[0], sizeof(queryResultsWithAvailabilityBit[0]), vk::VK_QUERY_RESULT_64_BIT | vk::VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
472 
473 		if (queryResult != vk::VK_NOT_READY)
474 		{
475 			TCU_FAIL("We don't have available one query, it should return VK_NOT_READY");
476 		}
477 
478 		log << tcu::TestLog::Section("TimestampQueryResults",
479 									 "Timestamp query results");
480 		for (int ndx = 0; ndx < NUM_QUERIES_IN_POOL; ++ndx)
481 		{
482 			log << tcu::TestLog::Message << "query[slot == " << ndx
483 				<< "] result == " << queryResultsWithAvailabilityBit[ndx].first << tcu::TestLog::EndMessage;
484 		}
485 
486 
487 		for (deUint32 queryNdx = 0; queryNdx < NUM_QUERIES_IN_POOL; ++queryNdx)
488 		{
489 			if (queryNdx == QUERY_INDEX_CAPTURE_EMPTY && (queryResultsWithAvailabilityBit[queryNdx].first != 0u || queryResultsWithAvailabilityBit[queryNdx].second != 0u))
490 			{
491 				log << tcu::TestLog::Message << "vkGetQueryPoolResults returned "
492 					"either wrong value of query for index "
493 					<< queryNdx << " (expected any zero value, got "
494 					<< queryResultsWithAvailabilityBit[queryNdx].first << ") or the result is available (" << queryResultsWithAvailabilityBit[queryNdx].second << ")"
495 					<< tcu::TestLog::EndMessage;
496 				passed = false;
497 			}
498 
499 			if (queryNdx != QUERY_INDEX_CAPTURE_EMPTY && (queryResultsWithAvailabilityBit[queryNdx].first == 0u || queryResultsWithAvailabilityBit[queryNdx].second == 0u))
500 			{
501 				log << tcu::TestLog::Message << "vkGetQueryPoolResults returned "
502 					"either wrong value of query for index "
503 					<< queryNdx << " (expected any non-zero value, got "
504 					<< queryResults[0] << ") or result is unavailable." << tcu::TestLog::EndMessage;
505 				passed = false;
506 			}
507 		}
508 		log << tcu::TestLog::EndSection;
509 	}
510 
511 	if (passed)
512 	{
513 		return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed");
514 	}
515 	return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed");
516 }
517 
518 class SecondaryCommandBufferConcurrentTestInstance : public vkt::TestInstance
519 {
520 public:
521 	SecondaryCommandBufferConcurrentTestInstance		(vkt::Context &context);
522 	~SecondaryCommandBufferConcurrentTestInstance		(void);
523 private:
524 	tcu::TestStatus					iterate							(void);
525 
526 	enum
527 	{
528 		NUM_QUERIES_IN_POOL				= 2,
529 		QUERY_INDEX_CAPTURE_EMPTY		= 0,
530 		QUERY_INDEX_CAPTURE_DRAWCALL	= 1,
531 		NUM_VERTICES_IN_DRAWCALL		= 3
532 	};
533 
534 	std::unique_ptr<StateObjects>			m_stateObjects;
535 	vk::Move<vk::VkQueryPool>				m_queryPools[NUM_QUERY_POOLS];
536 	deBool									m_supportedQueryType[NUM_QUERY_POOLS];
537 
538 };
539 
SecondaryCommandBufferConcurrentTestInstance(vkt::Context & context)540 SecondaryCommandBufferConcurrentTestInstance::SecondaryCommandBufferConcurrentTestInstance (vkt::Context &context)
541 	: TestInstance		(context)
542 {
543 	// Check support for multiple query types
544 	{
545 		for(deUint32 poolNdx = 0; poolNdx < NUM_QUERY_POOLS; poolNdx++)
546 			m_supportedQueryType[poolNdx] = DE_FALSE;
547 
548 		deUint32 numSupportedQueryTypes = 0;
549 		m_supportedQueryType[QUERY_TYPE_OCCLUSION] = DE_TRUE;
550 		numSupportedQueryTypes++;
551 
552 		if (context.getDeviceFeatures().pipelineStatisticsQuery)
553 		{
554 			m_supportedQueryType[QUERY_TYPE_PIPELINE_STATISTICS] = DE_TRUE;
555 			numSupportedQueryTypes++;
556 		}
557 
558 		// Check support for timestamp queries
559 		{
560 			const deUint32									queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
561 			const std::vector<vk::VkQueueFamilyProperties>	queueProperties		= vk::getPhysicalDeviceQueueFamilyProperties(context.getInstanceInterface(), context.getPhysicalDevice());
562 
563 			DE_ASSERT(queueFamilyIndex < (deUint32)queueProperties.size());
564 
565 			if (queueProperties[queueFamilyIndex].timestampValidBits)
566 			 {
567 				 m_supportedQueryType[QUERY_TYPE_TIMESTAMP] = DE_TRUE;
568 				 numSupportedQueryTypes++;
569 			 }
570 		}
571 		if (numSupportedQueryTypes < 2)
572 			throw tcu::NotSupportedError("Device does not support multiple query types");
573 	}
574 
575 	m_stateObjects = std::unique_ptr<StateObjects>(new StateObjects(m_context.getDeviceInterface(), m_context, NUM_VERTICES_IN_DRAWCALL, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
576 
577 	const vk::VkDevice			device	= m_context.getDevice();
578 	const vk::DeviceInterface&	vk		= m_context.getDeviceInterface();
579 
580 	for(deUint32 poolNdx = 0; poolNdx < NUM_QUERY_POOLS; poolNdx++)
581 	{
582 		if (!m_supportedQueryType[poolNdx])
583 			continue;
584 
585 		vk::VkQueryPoolCreateInfo queryPoolCreateInfo =
586 		{
587 			vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
588 			DE_NULL,
589 			0u,
590 			static_cast<vk::VkQueryType>(poolNdx),
591 			NUM_QUERIES_IN_POOL,
592 			0u,
593 		};
594 		if (poolNdx == QUERY_TYPE_PIPELINE_STATISTICS)
595 			queryPoolCreateInfo.pipelineStatistics = vk::VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT;
596 
597 		m_queryPools[poolNdx] = createQueryPool(vk, device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL);
598 	}
599 
600 	std::vector<tcu::Vec4> vertices(NUM_VERTICES_IN_DRAWCALL);
601 	vertices[0] = tcu::Vec4(0.5, 0.5, 0.0, 1.0);
602 	vertices[1] = tcu::Vec4(0.5, 0.0, 0.0, 1.0);
603 	vertices[2] = tcu::Vec4(0.0, 0.5, 0.0, 1.0);
604 	m_stateObjects->setVertices(vk, vertices);
605 }
606 
~SecondaryCommandBufferConcurrentTestInstance(void)607 SecondaryCommandBufferConcurrentTestInstance::~SecondaryCommandBufferConcurrentTestInstance (void)
608 {
609 }
610 
beginSecondaryCommandBuffer(const vk::DeviceInterface & vk,const vk::VkCommandBuffer secondaryCmdBuffer,const vk::VkCommandBufferInheritanceInfo bufferInheritanceInfo)611 void beginSecondaryCommandBuffer (const vk::DeviceInterface&				vk,
612 								  const vk::VkCommandBuffer					secondaryCmdBuffer,
613 								  const vk::VkCommandBufferInheritanceInfo	bufferInheritanceInfo)
614 {
615 	const vk::VkCommandBufferUsageFlags	flags		= bufferInheritanceInfo.renderPass != DE_NULL
616 													  ? (vk::VkCommandBufferUsageFlags)vk::VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT
617 													  : (vk::VkCommandBufferUsageFlags)0u;
618 	const vk::VkCommandBufferBeginInfo	beginInfo	=
619 	{
620 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,			// sType
621 		DE_NULL,													// pNext
622 		flags,														// flags
623 		&bufferInheritanceInfo,										// pInheritanceInfo
624 	};
625 	VK_CHECK(vk.beginCommandBuffer(secondaryCmdBuffer, &beginInfo));
626 }
627 
iterate(void)628 tcu::TestStatus	SecondaryCommandBufferConcurrentTestInstance::iterate (void)
629 {
630 	tcu::TestLog &log				= m_context.getTestContext().getLog();
631 	const vk::VkDevice device		= m_context.getDevice();
632 	const vk::VkQueue queue			= m_context.getUniversalQueue();
633 	const vk::DeviceInterface& vk	= m_context.getDeviceInterface();
634 	const deBool inheritedQueries	= m_context.getDeviceFeatures().inheritedQueries;
635 
636 	const CmdPoolCreateInfo			cmdPoolCreateInfo	(m_context.getUniversalQueueFamilyIndex());
637 	vk::Move<vk::VkCommandPool>		cmdPool				= vk::createCommandPool(vk, device, &cmdPoolCreateInfo);
638 
639 	vk::Unique<vk::VkCommandBuffer> cmdBufferPrimary			(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
640 	vk::Unique<vk::VkCommandBuffer> cmdBufferSecondary			(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
641 
642 	// Secondary command buffer recording.
643 	{
644 		// Begin secondary command buffer
645 		const vk::VkCommandBufferInheritanceInfo	secCmdBufInheritInfo	=
646 		{
647 			vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,
648 			DE_NULL,
649 			*m_stateObjects->m_renderPass,								// renderPass
650 			0u,															// subpass
651 			*m_stateObjects->m_framebuffer,								// framebuffer
652 			inheritedQueries ? VK_TRUE : VK_FALSE,						// occlusionQueryEnable
653 			(vk::VkQueryControlFlags)0u,								// queryFlags
654 			(vk::VkQueryPipelineStatisticFlags)0u,						// pipelineStatistics
655 		};
656 		beginSecondaryCommandBuffer(vk, *cmdBufferSecondary, secCmdBufInheritInfo);
657 
658 		vk.cmdBindPipeline(*cmdBufferSecondary, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stateObjects->m_pipeline);
659 		vk::VkBuffer vertexBuffer = m_stateObjects->m_vertexBuffer->object();
660 		const vk::VkDeviceSize vertexBufferOffset = 0;
661 		vk.cmdBindVertexBuffers(*cmdBufferSecondary, 0, 1, &vertexBuffer, &vertexBufferOffset);
662 
663 		if (!inheritedQueries && m_supportedQueryType[QUERY_TYPE_OCCLUSION])
664 			vk.cmdBeginQuery(*cmdBufferSecondary, *m_queryPools[QUERY_TYPE_OCCLUSION], QUERY_INDEX_CAPTURE_DRAWCALL, 0u);
665 
666 		// Run pipeline statistics queries capture in the second command buffer
667 		if (m_supportedQueryType[QUERY_TYPE_PIPELINE_STATISTICS])
668 			vk.cmdBeginQuery(*cmdBufferSecondary, *m_queryPools[QUERY_TYPE_PIPELINE_STATISTICS], QUERY_INDEX_CAPTURE_DRAWCALL, 0u);
669 
670 		// Timestamp query happening in the secondary command buffer
671 		if (m_supportedQueryType[QUERY_TYPE_TIMESTAMP])
672 			vk.cmdWriteTimestamp(*cmdBufferSecondary, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, *m_queryPools[QUERY_TYPE_TIMESTAMP], QUERY_INDEX_CAPTURE_DRAWCALL);
673 
674 		vk.cmdDraw(*cmdBufferSecondary, NUM_VERTICES_IN_DRAWCALL, 1, 0, 0);
675 
676 		if (m_supportedQueryType[QUERY_TYPE_PIPELINE_STATISTICS])
677 			vk.cmdEndQuery(*cmdBufferSecondary, *m_queryPools[QUERY_TYPE_PIPELINE_STATISTICS], QUERY_INDEX_CAPTURE_DRAWCALL);
678 
679 		if (!inheritedQueries && m_supportedQueryType[QUERY_TYPE_OCCLUSION])
680 			vk.cmdEndQuery(*cmdBufferSecondary, *m_queryPools[QUERY_TYPE_OCCLUSION], QUERY_INDEX_CAPTURE_DRAWCALL);
681 
682 		endCommandBuffer(vk, *cmdBufferSecondary);
683 	}
684 
685 	// Primary command buffer recording
686 	{
687 		beginCommandBuffer(vk, *cmdBufferPrimary);
688 
689 		initialTransitionColor2DImage(vk, *cmdBufferPrimary, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_LAYOUT_GENERAL,
690 									  vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
691 		initialTransitionDepth2DImage(vk, *cmdBufferPrimary, m_stateObjects->m_DepthImage->object(), vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
692 									  vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
693 
694 		std::vector<vk::VkClearValue> renderPassClearValues(2);
695 		deMemset(&renderPassClearValues[0], 0, static_cast<int>(renderPassClearValues.size()) * sizeof(vk::VkClearValue));
696 
697 		for (deUint32 poolNdx = 0u; poolNdx < NUM_QUERY_POOLS; poolNdx++)
698 		{
699 			if (m_supportedQueryType[poolNdx])
700 				vk.cmdResetQueryPool(*cmdBufferPrimary, *m_queryPools[poolNdx], 0u, NUM_QUERIES_IN_POOL);
701 		}
702 
703 		for (deUint32 poolNdx = 0u; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++)
704 		{
705 			if (m_supportedQueryType[poolNdx])
706 				vk.cmdBeginQuery(*cmdBufferPrimary, *m_queryPools[poolNdx], QUERY_INDEX_CAPTURE_EMPTY, 0u);
707 		}
708 
709 		for (deUint32 poolNdx = 0u; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++)
710 		{
711 			if (m_supportedQueryType[poolNdx])
712 				vk.cmdEndQuery(*cmdBufferPrimary, *m_queryPools[poolNdx], QUERY_INDEX_CAPTURE_EMPTY);
713 		}
714 
715 		// Run oclussion queries capture in the primary command buffer, inherit the counters for the secondary command buffer
716 		if (inheritedQueries && m_supportedQueryType[QUERY_TYPE_OCCLUSION])
717 			vk.cmdBeginQuery(*cmdBufferPrimary, *m_queryPools[QUERY_TYPE_OCCLUSION], QUERY_INDEX_CAPTURE_DRAWCALL, 0u);
718 
719 		beginRenderPass(vk, *cmdBufferPrimary, *m_stateObjects->m_renderPass, *m_stateObjects->m_framebuffer, vk::makeRect2D(0, 0, StateObjects::WIDTH, StateObjects::HEIGHT), (deUint32)renderPassClearValues.size(), &renderPassClearValues[0], vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
720 
721 		vk.cmdExecuteCommands(*cmdBufferPrimary, 1u, &cmdBufferSecondary.get());
722 
723 		endRenderPass(vk, *cmdBufferPrimary);
724 
725 		if (inheritedQueries && m_supportedQueryType[QUERY_TYPE_OCCLUSION])
726 			vk.cmdEndQuery(*cmdBufferPrimary, *m_queryPools[QUERY_TYPE_OCCLUSION], QUERY_INDEX_CAPTURE_DRAWCALL);
727 
728 		transition2DImage(vk, *cmdBufferPrimary,
729 						  m_stateObjects->m_colorAttachmentImage->object(),
730 						  vk::VK_IMAGE_ASPECT_COLOR_BIT,
731 						  vk::VK_IMAGE_LAYOUT_GENERAL,
732 						  vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
733 						  vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
734 						  vk::VK_ACCESS_TRANSFER_READ_BIT,
735 						  vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
736 						  vk::VK_PIPELINE_STAGE_TRANSFER_BIT);
737 
738 		endCommandBuffer(vk, *cmdBufferPrimary);
739 	}
740 
741 	submitCommandsAndWait(vk, device, queue, cmdBufferPrimary.get());
742 
743 	deUint64 queryResults[NUM_QUERIES_IN_POOL] = { 0 };
744 	size_t queryResultsSize		= sizeof(queryResults);
745 	bool passed = true;
746 
747 	// Occlusion and pipeline statistics queries verification
748 	for (deUint32 poolNdx = 0; poolNdx < QUERY_TYPE_TIMESTAMP; poolNdx++)
749 	{
750 		if (!m_supportedQueryType[poolNdx])
751 			continue;
752 		vk::VkResult queryResult	= vk.getQueryPoolResults(device, *m_queryPools[poolNdx], 0, NUM_QUERIES_IN_POOL, queryResultsSize, queryResults, sizeof(queryResults[0]), vk::VK_QUERY_RESULT_64_BIT);
753 
754 		if (queryResult == vk::VK_NOT_READY)
755 		{
756 			TCU_FAIL("Query result not available, but vkWaitIdle() was called.");
757 		}
758 
759 		VK_CHECK(queryResult);
760 		std::string name = (poolNdx == QUERY_TYPE_OCCLUSION) ? "OcclusionQueryResults" : "PipelineStatisticsQueryResults";
761 		std::string desc = (poolNdx == QUERY_TYPE_OCCLUSION) ? "Occlusion query results" : "PipelineStatistics query results";
762 		log << tcu::TestLog::Section(name, desc);
763 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(queryResults); ++ndx)
764 		{
765 			log << tcu::TestLog::Message << "query[slot == " << ndx
766 				<< "] result == " << queryResults[ndx] << tcu::TestLog::EndMessage;
767 		}
768 
769 		for (deUint32 queryNdx = 0; queryNdx < DE_LENGTH_OF_ARRAY(queryResults); ++queryNdx)
770 		{
771 			if (queryNdx == QUERY_INDEX_CAPTURE_EMPTY && queryResults[queryNdx] != 0u)
772 			{
773 				log << tcu::TestLog::Message << "vkGetQueryPoolResults returned "
774 					"wrong value of query for index "
775 					<< queryNdx << ", expected any zero value, got "
776 					<< queryResults[0] << "." << tcu::TestLog::EndMessage;
777 				passed = false;
778 			}
779 
780 			if (queryNdx != QUERY_INDEX_CAPTURE_EMPTY && queryResults[queryNdx] == 0)
781 			{
782 				log << tcu::TestLog::Message << "vkGetQueryPoolResults returned "
783 					"wrong value of query for index "
784 					<< queryNdx << ", expected any non-zero value, got "
785 					<< queryResults[0] << "." << tcu::TestLog::EndMessage;
786 				passed = false;
787 			}
788 		}
789 		log << tcu::TestLog::EndSection;
790 	}
791 
792 	// Timestamp query verification
793 	if (m_supportedQueryType[QUERY_TYPE_TIMESTAMP])
794 	{
795 		std::pair<deUint64, deUint64>	queryResultsWithAvailabilityBit[NUM_QUERIES_IN_POOL];
796 		size_t queryResultsWithAvailabilityBitSize		= sizeof(queryResultsWithAvailabilityBit);
797 		vk::VkResult queryResult	= vk.getQueryPoolResults(device, *m_queryPools[QUERY_TYPE_TIMESTAMP], 0, NUM_QUERIES_IN_POOL, queryResultsWithAvailabilityBitSize, &queryResultsWithAvailabilityBit[0], sizeof(queryResultsWithAvailabilityBit[0]), vk::VK_QUERY_RESULT_64_BIT | vk::VK_QUERY_RESULT_WITH_AVAILABILITY_BIT);
798 
799 		if (queryResult != vk::VK_NOT_READY)
800 		{
801 			TCU_FAIL("We don't have available one query, it should return VK_NOT_READY");
802 		}
803 
804 		log << tcu::TestLog::Section("TimestampQueryResults",
805 									 "Timestamp query results");
806 		for (int ndx = 0; ndx < NUM_QUERIES_IN_POOL; ++ndx)
807 		{
808 			log << tcu::TestLog::Message << "query[slot == " << ndx
809 				<< "] result == " << queryResultsWithAvailabilityBit[ndx].first << tcu::TestLog::EndMessage;
810 		}
811 
812 
813 		for (deUint32 queryNdx = 0; queryNdx < NUM_QUERIES_IN_POOL; ++queryNdx)
814 		{
815 			if (queryNdx == QUERY_INDEX_CAPTURE_EMPTY && (queryResultsWithAvailabilityBit[queryNdx].first != 0u || queryResultsWithAvailabilityBit[queryNdx].second != 0u))
816 			{
817 				log << tcu::TestLog::Message << "vkGetQueryPoolResults returned "
818 					"either wrong value of query for index "
819 					<< queryNdx << " (expected any zero value, got "
820 					<< queryResultsWithAvailabilityBit[queryNdx].first << ") or the result is available (" << queryResultsWithAvailabilityBit[queryNdx].second << ")"
821 					<< tcu::TestLog::EndMessage;
822 				passed = false;
823 			}
824 
825 			if (queryNdx != QUERY_INDEX_CAPTURE_EMPTY && (queryResultsWithAvailabilityBit[queryNdx].first == 0u || queryResultsWithAvailabilityBit[queryNdx].second == 0u))
826 			{
827 				log << tcu::TestLog::Message << "vkGetQueryPoolResults returned "
828 					"either wrong value of query for index "
829 					<< queryNdx << " (expected any non-zero value, got "
830 					<< queryResults[0] << ") or result is unavailable." << tcu::TestLog::EndMessage;
831 				passed = false;
832 			}
833 		}
834 		log << tcu::TestLog::EndSection;
835 	}
836 
837 	if (passed)
838 	{
839 		return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed");
840 	}
841 	return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed");
842 }
843 
844 template<class Instance>
845 class QueryPoolConcurrentTest : public vkt::TestCase
846 {
847 public:
QueryPoolConcurrentTest(tcu::TestContext & context,const char * name,const char * description)848 	QueryPoolConcurrentTest (tcu::TestContext &context, const char *name, const char *description)
849 		: TestCase			(context, name, description)
850 	{
851 	}
852 private:
createInstance(vkt::Context & context) const853 	vkt::TestInstance* createInstance (vkt::Context& context) const
854 	{
855 		return new Instance(context);
856 	}
857 
initPrograms(vk::SourceCollections & programCollection) const858 	void initPrograms(vk::SourceCollections& programCollection) const
859 	{
860 		const std::string fragSrc = std::string(
861 			"#version 400\n"
862 			"layout(location = 0) out vec4 out_FragColor;\n"
863 			"void main()\n"
864 			"{\n"
865 			"	out_FragColor = vec4(0.07, 0.48, 0.75, 1.0);\n"
866 			"	if ((int(gl_FragCoord.x) % 2) == (int(gl_FragCoord.y) % 2))\n"
867 			"		discard;\n"
868 			"}");
869 
870 		programCollection.glslSources.add("frag") << glu::FragmentSource(fragSrc.c_str());
871 
872 		programCollection.glslSources.add("vert") << glu::VertexSource("#version 430\n"
873 																		 "layout(location = 0) in vec4 in_Position;\n"
874 																		 "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };\n"
875 																		 "void main() {\n"
876 																		 "	gl_Position  = in_Position;\n"
877 																		 "	gl_PointSize = 1.0;\n"
878 																		 "}\n");
879 	}
880 };
881 
882 } //anonymous
883 
QueryPoolConcurrentTests(tcu::TestContext & testCtx)884 QueryPoolConcurrentTests::QueryPoolConcurrentTests (tcu::TestContext &testCtx)
885 	: TestCaseGroup(testCtx, "concurrent_queries", "Tests for concurrent queries")
886 {
887 	/* Left blank on purpose */
888 }
889 
~QueryPoolConcurrentTests(void)890 QueryPoolConcurrentTests::~QueryPoolConcurrentTests (void)
891 {
892 	/* Left blank on purpose */
893 }
894 
init(void)895 void QueryPoolConcurrentTests::init (void)
896 {
897 	addChild(new QueryPoolConcurrentTest<PrimaryCommandBufferConcurrentTestInstance>(m_testCtx, "primary_command_buffer", ""));
898 	addChild(new QueryPoolConcurrentTest<SecondaryCommandBufferConcurrentTestInstance>(m_testCtx, "secondary_command_buffer", ""));
899 }
900 
901 } //QueryPool
902 } //vkt
903