Home | History | Annotate | Download | only in query_pool
      1 /*------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2015 The Khronos Group Inc.
      6  * Copyright (c) 2015 Intel Corporation
      7  *
      8  * Licensed under the Apache License, Version 2.0 (the "License");
      9  * you may not use this file except in compliance with the License.
     10  * You may obtain a copy of the License at
     11  *
     12  *      http://www.apache.org/licenses/LICENSE-2.0
     13  *
     14  * Unless required by applicable law or agreed to in writing, software
     15  * distributed under the License is distributed on an "AS IS" BASIS,
     16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     17  * See the License for the specific language governing permissions and
     18  * limitations under the License.
     19  *
     20  *//*!
     21  * \file
     22  * \brief Vulkan Occlusion Query Tests
     23  *//*--------------------------------------------------------------------*/
     24 
     25 #include "vktQueryPoolOcclusionTests.hpp"
     26 
     27 #include "vktTestCase.hpp"
     28 
     29 #include "vktQueryPoolImageObjectUtil.hpp"
     30 #include "vktQueryPoolBufferObjectUtil.hpp"
     31 #include "vktQueryPoolCreateInfoUtil.hpp"
     32 #include "vkBuilderUtil.hpp"
     33 #include "vkRefUtil.hpp"
     34 #include "vkPrograms.hpp"
     35 
     36 #include "tcuTestLog.hpp"
     37 #include "tcuResource.hpp"
     38 #include "tcuImageCompare.hpp"
     39 #include "tcuCommandLine.hpp"
     40 
     41 using namespace vkt::QueryPool;
     42 
     43 namespace
     44 {
     45 
     46 struct StateObjects
     47 {
     48 			StateObjects	(const vk::DeviceInterface&vk, vkt::Context &context, const int numVertices, vk::VkPrimitiveTopology primitive);
     49 	void	setVertices		(const vk::DeviceInterface&vk, std::vector<tcu::Vec4> vertices);
     50 
     51 	enum
     52 	{
     53 		WIDTH	= 128,
     54 		HEIGHT	= 128
     55 	};
     56 
     57 	vkt::Context &m_context;
     58 
     59 	vk::Move<vk::VkPipeline>		m_pipeline;
     60 	vk::Move<vk::VkPipelineLayout>	m_pipelineLayout;
     61 
     62 	de::SharedPtr<Image>			m_colorAttachmentImage, m_DepthImage;
     63 	vk::Move<vk::VkImageView>		m_attachmentView;
     64 	vk::Move<vk::VkImageView>		m_depthiew;
     65 
     66 	vk::Move<vk::VkRenderPass>		m_renderPass;
     67 	vk::Move<vk::VkFramebuffer>		m_framebuffer;
     68 
     69 	de::SharedPtr<Buffer>			m_vertexBuffer;
     70 
     71 	vk::VkFormat					m_colorAttachmentFormat;
     72 };
     73 
     74 StateObjects::StateObjects (const vk::DeviceInterface&vk, vkt::Context &context, const int numVertices, vk::VkPrimitiveTopology primitive)
     75 	: m_context(context)
     76 	, m_colorAttachmentFormat(vk::VK_FORMAT_R8G8B8A8_UNORM)
     77 
     78 {
     79 	vk::VkFormat		depthFormat = vk::VK_FORMAT_D16_UNORM;
     80 	const vk::VkDevice	device		= m_context.getDevice();
     81 
     82 	//attachment images and views
     83 	{
     84 		vk::VkExtent3D imageExtent =
     85 		{
     86 			WIDTH,	// width;
     87 			HEIGHT,	// height;
     88 			1		// depth;
     89 		};
     90 
     91 		const ImageCreateInfo colorImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_colorAttachmentFormat, imageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL,
     92 												   vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
     93 
     94 		m_colorAttachmentImage	= Image::createAndAlloc(vk, device, colorImageCreateInfo, m_context.getDefaultAllocator());
     95 
     96 		const ImageViewCreateInfo attachmentViewInfo(m_colorAttachmentImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
     97 		m_attachmentView		= vk::createImageView(vk, device, &attachmentViewInfo);
     98 
     99 		ImageCreateInfo depthImageCreateInfo(vk::VK_IMAGE_TYPE_2D, depthFormat, imageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL,
    100 			vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
    101 
    102 		m_DepthImage			= Image::createAndAlloc(vk, device, depthImageCreateInfo, m_context.getDefaultAllocator());
    103 
    104 		// Construct a depth  view from depth image
    105 		const ImageViewCreateInfo depthViewInfo(m_DepthImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, depthFormat);
    106 		m_depthiew				= vk::createImageView(vk, device, &depthViewInfo);
    107 	}
    108 
    109 	{
    110 		// Renderpass and Framebuffer
    111 
    112 		RenderPassCreateInfo renderPassCreateInfo;
    113 		renderPassCreateInfo.addAttachment(AttachmentDescription(m_colorAttachmentFormat,									// format
    114 																	vk::VK_SAMPLE_COUNT_1_BIT,								// samples
    115 																	vk::VK_ATTACHMENT_LOAD_OP_CLEAR,						// loadOp
    116 																	vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,					// storeOp
    117 																	vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// stencilLoadOp
    118 																	vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,					// stencilLoadOp
    119 																	vk::VK_IMAGE_LAYOUT_GENERAL,							// initialLauout
    120 																	vk::VK_IMAGE_LAYOUT_GENERAL));							// finalLayout
    121 
    122 		renderPassCreateInfo.addAttachment(AttachmentDescription(depthFormat,												// format
    123 																 vk::VK_SAMPLE_COUNT_1_BIT,									// samples
    124 																 vk::VK_ATTACHMENT_LOAD_OP_CLEAR,							// loadOp
    125 																 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,						// storeOp
    126 																 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,						// stencilLoadOp
    127 																 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,						// stencilLoadOp
    128 																 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,		// initialLauout
    129 																 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));	// finalLayout
    130 
    131 		const vk::VkAttachmentReference colorAttachmentReference =
    132 		{
    133 			0,															// attachment
    134 			vk::VK_IMAGE_LAYOUT_GENERAL									// layout
    135 		};
    136 
    137 		const vk::VkAttachmentReference depthAttachmentReference =
    138 		{
    139 			1,															// attachment
    140 			vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL		// layout
    141 		};
    142 
    143 		renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS,					// pipelineBindPoint
    144 														   0,													// flags
    145 														   0,													// inputCount
    146 														   DE_NULL,												// pInputAttachments
    147 														   1,													// colorCount
    148 														   &colorAttachmentReference,							// pColorAttachments
    149 														   DE_NULL,												// pResolveAttachments
    150 														   depthAttachmentReference,							// depthStencilAttachment
    151 														   0,													// preserveCount
    152 														   DE_NULL));											// preserveAttachments
    153 
    154 		m_renderPass = vk::createRenderPass(vk, device, &renderPassCreateInfo);
    155 
    156 		std::vector<vk::VkImageView> attachments(2);
    157 		attachments[0] = *m_attachmentView;
    158 		attachments[1] = *m_depthiew;
    159 
    160 		FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, attachments, WIDTH, HEIGHT, 1);
    161 		m_framebuffer = vk::createFramebuffer(vk, device, &framebufferCreateInfo);
    162 	}
    163 
    164 	{
    165 		// Pipeline
    166 
    167 		vk::Unique<vk::VkShaderModule> vs(vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
    168 		vk::Unique<vk::VkShaderModule> fs(vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
    169 
    170 		const PipelineCreateInfo::ColorBlendState::Attachment attachmentState;
    171 
    172 		const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
    173 		m_pipelineLayout = vk::createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
    174 
    175 		const vk::VkVertexInputBindingDescription vf_binding_desc		=
    176 		{
    177 			0,																// binding;
    178 			4 * (deUint32)sizeof(float),									// stride;
    179 			vk::VK_VERTEX_INPUT_RATE_VERTEX									// inputRate
    180 		};
    181 
    182 		const vk::VkVertexInputAttributeDescription vf_attribute_desc	=
    183 		{
    184 			0,																// location;
    185 			0,																// binding;
    186 			vk::VK_FORMAT_R32G32B32A32_SFLOAT,								// format;
    187 			0																// offset;
    188 		};
    189 
    190 		const vk::VkPipelineVertexInputStateCreateInfo vf_info			=
    191 		{																	// sType;
    192 			vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// pNext;
    193 			NULL,															// flags;
    194 			0u,																// vertexBindingDescriptionCount;
    195 			1,																// pVertexBindingDescriptions;
    196 			&vf_binding_desc,												// vertexAttributeDescriptionCount;
    197 			1,																// pVertexAttributeDescriptions;
    198 			&vf_attribute_desc
    199 		};
    200 
    201 		PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
    202 		pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
    203 		pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
    204 		pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(primitive));
    205 		pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &attachmentState));
    206 		const vk::VkViewport viewport	=
    207 		{
    208 			0,		// float x;
    209 			0,		// float y;
    210 			WIDTH,	// float width;
    211 			HEIGHT,	// float height;
    212 			0.0f,	// float minDepth;
    213 			1.0f	// float maxDepth;
    214 		};
    215 
    216 		const vk::VkRect2D scissor		=
    217 		{
    218 			{
    219 				0,		// deInt32 x
    220 				0,		// deInt32 y
    221 			},		// VkOffset2D	offset;
    222 			{
    223 				WIDTH,	// deInt32 width;
    224 				HEIGHT,	// deInt32 height
    225 			},		// VkExtent2D	extent;
    226 		};
    227 		pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport), std::vector<vk::VkRect2D>(1, scissor)));
    228 		pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState(true, true, vk::VK_COMPARE_OP_GREATER_OR_EQUAL));
    229 		pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
    230 		pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
    231 		pipelineCreateInfo.addState(vf_info);
    232 		m_pipeline = vk::createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
    233 	}
    234 
    235 	{
    236 		// Vertex buffer
    237 		const size_t kBufferSize = numVertices * sizeof(tcu::Vec4);
    238 		m_vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(kBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
    239 	}
    240 }
    241 
    242 void StateObjects::setVertices (const vk::DeviceInterface&vk, std::vector<tcu::Vec4> vertices)
    243 {
    244 	const vk::VkDevice device			= m_context.getDevice();
    245 
    246 	tcu::Vec4 *ptr = reinterpret_cast<tcu::Vec4*>(m_vertexBuffer->getBoundMemory().getHostPtr());
    247 	std::copy(vertices.begin(), vertices.end(), ptr);
    248 
    249 	vk::flushMappedMemoryRange(vk, device,	m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(),	vertices.size() * sizeof(vertices[0]));
    250 }
    251 
    252 enum OcclusionQueryResultSize
    253 {
    254 	RESULT_SIZE_64_BIT,
    255 	RESULT_SIZE_32_BIT,
    256 };
    257 
    258 enum OcclusionQueryWait
    259 {
    260 	WAIT_QUEUE,
    261 	WAIT_QUERY,
    262 	WAIT_NONE
    263 };
    264 
    265 enum OcclusionQueryResultsMode
    266 {
    267 	RESULTS_MODE_GET,
    268 	RESULTS_MODE_COPY
    269 };
    270 
    271 struct OcclusionQueryTestVector
    272 {
    273 	vk::VkQueryControlFlags		queryControlFlags;
    274 	OcclusionQueryResultSize	queryResultSize;
    275 	OcclusionQueryWait			queryWait;
    276 	OcclusionQueryResultsMode	queryResultsMode;
    277 	vk::VkDeviceSize			queryResultsStride;
    278 	bool						queryResultsAvailability;
    279 	vk::VkPrimitiveTopology		primitiveTopology;
    280 };
    281 
    282 class BasicOcclusionQueryTestInstance : public vkt::TestInstance
    283 {
    284 public:
    285 					BasicOcclusionQueryTestInstance		(vkt::Context &context, const OcclusionQueryTestVector&  testVector);
    286 					~BasicOcclusionQueryTestInstance	(void);
    287 private:
    288 	tcu::TestStatus	iterate								(void);
    289 
    290 	enum
    291 	{
    292 		NUM_QUERIES_IN_POOL				= 2,
    293 		QUERY_INDEX_CAPTURE_EMPTY		= 0,
    294 		QUERY_INDEX_CAPTURE_DRAWCALL	= 1,
    295 		NUM_VERTICES_IN_DRAWCALL		= 3
    296 	};
    297 
    298 	OcclusionQueryTestVector	m_testVector;
    299 	StateObjects*				m_stateObjects;
    300 	vk::VkQueryPool				m_queryPool;
    301 };
    302 
    303 BasicOcclusionQueryTestInstance::BasicOcclusionQueryTestInstance (vkt::Context &context, const OcclusionQueryTestVector&  testVector)
    304 	: TestInstance		(context)
    305 	, m_testVector		(testVector)
    306 {
    307 	DE_ASSERT(testVector.queryResultSize			== RESULT_SIZE_64_BIT
    308 			&& testVector.queryWait					== WAIT_QUEUE
    309 			&& testVector.queryResultsMode			== RESULTS_MODE_GET
    310 			&& testVector.queryResultsStride		== sizeof(deUint64)
    311 			&& testVector.queryResultsAvailability	== false
    312 			&& testVector.primitiveTopology			== vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
    313 
    314 	if ((m_testVector.queryControlFlags & vk::VK_QUERY_CONTROL_PRECISE_BIT) && !m_context.getDeviceFeatures().occlusionQueryPrecise)
    315 		throw tcu::NotSupportedError("Precise occlusion queries are not supported");
    316 
    317 	m_stateObjects = new StateObjects(m_context.getDeviceInterface(), m_context, NUM_VERTICES_IN_DRAWCALL, m_testVector.primitiveTopology);
    318 
    319 	const vk::VkDevice			device	= m_context.getDevice();
    320 	const vk::DeviceInterface&	vk		= m_context.getDeviceInterface();
    321 
    322 	const vk::VkQueryPoolCreateInfo queryPoolCreateInfo =
    323 	{
    324 		vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
    325 		DE_NULL,
    326 		0u,
    327 		vk::VK_QUERY_TYPE_OCCLUSION,
    328 		NUM_QUERIES_IN_POOL,
    329 		0
    330 	};
    331 	VK_CHECK(vk.createQueryPool(device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL, &m_queryPool));
    332 
    333 	std::vector<tcu::Vec4> vertices(NUM_VERTICES_IN_DRAWCALL);
    334 	vertices[0] = tcu::Vec4(0.5, 0.5, 0.0, 1.0);
    335 	vertices[1] = tcu::Vec4(0.5, 0.0, 0.0, 1.0);
    336 	vertices[2] = tcu::Vec4(0.0, 0.5, 0.0, 1.0);
    337 	m_stateObjects->setVertices(vk, vertices);
    338 }
    339 
    340 BasicOcclusionQueryTestInstance::~BasicOcclusionQueryTestInstance (void)
    341 {
    342 	if (m_stateObjects)
    343 		delete m_stateObjects;
    344 
    345 	if (m_queryPool != DE_NULL)
    346 	{
    347 		const vk::VkDevice device		= m_context.getDevice();
    348 		const vk::DeviceInterface& vk	= m_context.getDeviceInterface();
    349 
    350 		vk.destroyQueryPool(device, m_queryPool, /*pAllocator*/ DE_NULL);
    351 	}
    352 }
    353 
    354 tcu::TestStatus	BasicOcclusionQueryTestInstance::iterate (void)
    355 {
    356 	tcu::TestLog &log				= m_context.getTestContext().getLog();
    357 	const vk::VkDevice device		= m_context.getDevice();
    358 	const vk::VkQueue queue			= m_context.getUniversalQueue();
    359 	const vk::DeviceInterface& vk	= m_context.getDeviceInterface();
    360 
    361 	const CmdPoolCreateInfo			cmdPoolCreateInfo	(m_context.getUniversalQueueFamilyIndex());
    362 	vk::Move<vk::VkCommandPool>		cmdPool				= vk::createCommandPool(vk, device, &cmdPoolCreateInfo);
    363 
    364 	const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
    365 	{
    366 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
    367 		DE_NULL,											// const void*				pNext;
    368 		*cmdPool,											// VkCommandPool			commandPool;
    369 		vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
    370 		1u,													// deUint32					bufferCount;
    371 	};
    372 	vk::Unique<vk::VkCommandBuffer> cmdBuffer			(vk::allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo));
    373 	const CmdBufferBeginInfo		beginInfo			(0u);
    374 
    375 	vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
    376 
    377 	transition2DImage(vk, *cmdBuffer, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, 0, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
    378 	transition2DImage(vk, *cmdBuffer, m_stateObjects->m_DepthImage->object(), vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 0, vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
    379 
    380 	std::vector<vk::VkClearValue> renderPassClearValues(2);
    381 	deMemset(&renderPassClearValues[0], 0, static_cast<int>(renderPassClearValues.size()) * sizeof(vk::VkClearValue));
    382 
    383 	const vk::VkRect2D renderArea =
    384 	{
    385 		{ 0,					0 },
    386 		{ StateObjects::WIDTH,	StateObjects::HEIGHT }
    387 	};
    388 
    389 	RenderPassBeginInfo renderPassBegin(*m_stateObjects->m_renderPass, *m_stateObjects->m_framebuffer, renderArea, renderPassClearValues);
    390 
    391 	vk.cmdResetQueryPool(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL);
    392 
    393 	vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBegin, vk::VK_SUBPASS_CONTENTS_INLINE);
    394 
    395 	vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stateObjects->m_pipeline);
    396 
    397 	vk::VkBuffer vertexBuffer = m_stateObjects->m_vertexBuffer->object();
    398 	const vk::VkDeviceSize vertexBufferOffset = 0;
    399 	vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
    400 
    401 	vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_EMPTY, m_testVector.queryControlFlags);
    402 	vk.cmdEndQuery(*cmdBuffer, m_queryPool,	QUERY_INDEX_CAPTURE_EMPTY);
    403 
    404 	vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_DRAWCALL, m_testVector.queryControlFlags);
    405 	vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, 0, 0);
    406 	vk.cmdEndQuery(*cmdBuffer, m_queryPool,	QUERY_INDEX_CAPTURE_DRAWCALL);
    407 
    408 	vk.cmdEndRenderPass(*cmdBuffer);
    409 
    410 	transition2DImage(vk, *cmdBuffer, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT);
    411 
    412 	vk.endCommandBuffer(*cmdBuffer);
    413 
    414 	// Submit command buffer
    415 	const vk::VkSubmitInfo submitInfo =
    416 	{
    417 		vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
    418 		DE_NULL,							// const void*				pNext;
    419 		0,									// deUint32					waitSemaphoreCount;
    420 		DE_NULL,							// const VkSemaphore*		pWaitSemaphores;
    421 		(const vk::VkPipelineStageFlags*)DE_NULL,
    422 		1,									// deUint32					commandBufferCount;
    423 		&cmdBuffer.get(),					// const VkCommandBuffer*	pCommandBuffers;
    424 		0,									// deUint32					signalSemaphoreCount;
    425 		DE_NULL								// const VkSemaphore*		pSignalSemaphores;
    426 	};
    427 	vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
    428 
    429 	VK_CHECK(vk.queueWaitIdle(queue));
    430 
    431 	deUint64 queryResults[NUM_QUERIES_IN_POOL] = { 0 };
    432 	size_t queryResultsSize		= sizeof(queryResults);
    433 
    434 	vk::VkResult queryResult	= vk.getQueryPoolResults(device, m_queryPool, 0, NUM_QUERIES_IN_POOL, queryResultsSize, queryResults, sizeof(queryResults[0]), vk::VK_QUERY_RESULT_64_BIT);
    435 
    436 	if (queryResult == vk::VK_NOT_READY)
    437 	{
    438 		TCU_FAIL("Query result not avaliable, but vkWaitIdle() was called.");
    439 	}
    440 
    441 	VK_CHECK(queryResult);
    442 
    443 	log << tcu::TestLog::Section("OcclusionQueryResults",
    444 		"Occlusion query results");
    445 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(queryResults); ++ndx)
    446 	{
    447 		log << tcu::TestLog::Message << "query[ slot == " << ndx
    448 			<< "] result == " << queryResults[ndx] << tcu::TestLog::EndMessage;
    449 	}
    450 
    451 	bool passed = true;
    452 
    453 	for (int queryNdx = 0; queryNdx < DE_LENGTH_OF_ARRAY(queryResults); ++queryNdx)
    454 	{
    455 
    456 		deUint64 expectedValue;
    457 
    458 		switch (queryNdx)
    459 		{
    460 			case QUERY_INDEX_CAPTURE_EMPTY:
    461 				expectedValue = 0;
    462 				break;
    463 			case QUERY_INDEX_CAPTURE_DRAWCALL:
    464 				expectedValue = NUM_VERTICES_IN_DRAWCALL;
    465 				break;
    466 		}
    467 
    468 		if ((m_testVector.queryControlFlags & vk::VK_QUERY_CONTROL_PRECISE_BIT) || expectedValue == 0)
    469 		{
    470 			// require precise value
    471 			if (queryResults[queryNdx] != expectedValue)
    472 			{
    473 				log << tcu::TestLog::Message << "vkGetQueryPoolResults returned "
    474 					"wrong value of query for index "
    475 					<< queryNdx << ", expected " << expectedValue << ", got "
    476 					<< queryResults[0] << "." << tcu::TestLog::EndMessage;
    477 				passed = false;
    478 			}
    479 		}
    480 		else
    481 		{
    482 			// require imprecize value > 0
    483 			if (queryResults[queryNdx] == 0)
    484 			{
    485 				log << tcu::TestLog::Message << "vkGetQueryPoolResults returned "
    486 					"wrong value of query for index "
    487 					<< queryNdx << ", expected any non-zero value, got "
    488 					<< queryResults[0] << "." << tcu::TestLog::EndMessage;
    489 				passed = false;
    490 			}
    491 		}
    492 	}
    493 	log << tcu::TestLog::EndSection;
    494 
    495 	if (passed)
    496 	{
    497 		return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed");
    498 	}
    499 	return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed");
    500 }
    501 
    502 class OcclusionQueryTestInstance : public vkt::TestInstance
    503 {
    504 public:
    505 	OcclusionQueryTestInstance		(vkt::Context &context, const OcclusionQueryTestVector& testVector);
    506 	~OcclusionQueryTestInstance		(void);
    507 private:
    508 	tcu::TestStatus					iterate							(void);
    509 
    510 	vk::Move<vk::VkCommandBuffer>	recordRender					(vk::VkCommandPool commandPool);
    511 	vk::Move<vk::VkCommandBuffer>	recordCopyResults				(vk::VkCommandPool commandPool);
    512 
    513 	void							captureResults					(deUint64*			retResults,	deUint64*		retAvailability,	bool	allowNotReady);
    514 	void							logResults						(const deUint64*	results,	const deUint64* availability);
    515 	bool							validateResults					(const deUint64*	results,	const deUint64* availability,		bool	allowUnavailable,	vk::VkPrimitiveTopology primitiveTopology);
    516 
    517 	enum
    518 	{
    519 		NUM_QUERIES_IN_POOL							= 3,
    520 		QUERY_INDEX_CAPTURE_ALL						= 0,
    521 		QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED		= 1,
    522 		QUERY_INDEX_CAPTURE_OCCLUDED				= 2
    523 	};
    524 	enum
    525 	{
    526 		NUM_VERTICES_IN_DRAWCALL					= 3,
    527 		NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL	= 3,
    528 		NUM_VERTICES_IN_OCCLUDER_DRAWCALL			= 3,
    529 		NUM_VERTICES								= NUM_VERTICES_IN_DRAWCALL + NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL + NUM_VERTICES_IN_OCCLUDER_DRAWCALL
    530 	};
    531 	enum
    532 	{
    533 		START_VERTEX								= 0,
    534 		START_VERTEX_PARTIALLY_OCCLUDED				= START_VERTEX + NUM_VERTICES_IN_DRAWCALL,
    535 		START_VERTEX_OCCLUDER						= START_VERTEX_PARTIALLY_OCCLUDED + NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL
    536 	};
    537 
    538 	OcclusionQueryTestVector		m_testVector;
    539 
    540 	const vk::VkQueryResultFlags	m_queryResultFlags;
    541 
    542 	StateObjects*					m_stateObjects;
    543 	vk::VkQueryPool					m_queryPool;
    544 	de::SharedPtr<Buffer>			m_queryPoolResultsBuffer;
    545 
    546 	vk::Move<vk::VkCommandPool>		m_commandPool;
    547 	vk::Move<vk::VkCommandBuffer>	m_renderCommandBuffer;
    548 	vk::Move<vk::VkCommandBuffer>	m_copyResultsCommandBuffer;
    549 };
    550 
    551 OcclusionQueryTestInstance::OcclusionQueryTestInstance (vkt::Context &context, const OcclusionQueryTestVector& testVector)
    552 	: vkt::TestInstance		(context)
    553 	, m_testVector			(testVector)
    554 	, m_queryResultFlags	((m_testVector.queryWait == WAIT_QUERY					? vk::VK_QUERY_RESULT_WAIT_BIT				: 0)
    555 							| (m_testVector.queryResultSize == RESULT_SIZE_64_BIT	? vk::VK_QUERY_RESULT_64_BIT				: 0)
    556 							| (m_testVector.queryResultsAvailability				? vk::VK_QUERY_RESULT_WITH_AVAILABILITY_BIT	: 0))
    557 {
    558 	const vk::VkDevice			device				= m_context.getDevice();
    559 	const vk::DeviceInterface&	vk					= m_context.getDeviceInterface();
    560 
    561 	if ((m_testVector.queryControlFlags & vk::VK_QUERY_CONTROL_PRECISE_BIT) && !m_context.getDeviceFeatures().occlusionQueryPrecise)
    562 		throw tcu::NotSupportedError("Precise occlusion queries are not supported");
    563 
    564 	m_stateObjects  = new StateObjects(m_context.getDeviceInterface(), m_context, NUM_VERTICES_IN_DRAWCALL + NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL + NUM_VERTICES_IN_OCCLUDER_DRAWCALL, m_testVector.primitiveTopology);
    565 
    566 	const vk::VkQueryPoolCreateInfo queryPoolCreateInfo	=
    567 	{
    568 		vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
    569 		DE_NULL,
    570 		0u,
    571 		vk::VK_QUERY_TYPE_OCCLUSION,
    572 		NUM_QUERIES_IN_POOL,
    573 		0
    574 	};
    575 
    576 	VK_CHECK(vk.createQueryPool(device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL, &m_queryPool));
    577 
    578 	if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
    579 	{
    580 		const vk::VkDeviceSize	resultsBufferSize			= m_testVector.queryResultsStride * NUM_QUERIES_IN_POOL;
    581 								m_queryPoolResultsBuffer	= Buffer::createAndAlloc(vk, device, BufferCreateInfo(resultsBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
    582 	}
    583 
    584 	const CmdPoolCreateInfo	cmdPoolCreateInfo		(m_context.getUniversalQueueFamilyIndex());
    585 							m_commandPool			= vk::createCommandPool(vk, device, &cmdPoolCreateInfo);
    586 							m_renderCommandBuffer	= recordRender(*m_commandPool);
    587 
    588 	if (m_testVector.queryWait == WAIT_QUEUE && m_testVector.queryResultsMode == RESULTS_MODE_COPY)
    589 	{
    590 		m_copyResultsCommandBuffer = recordCopyResults(*m_commandPool);
    591 	}
    592 }
    593 
    594 OcclusionQueryTestInstance::~OcclusionQueryTestInstance (void)
    595 {
    596 	const vk::VkDevice device = m_context.getDevice();
    597 
    598 	if (m_stateObjects)
    599 		delete m_stateObjects;
    600 
    601 	if (m_queryPool != DE_NULL)
    602 	{
    603 		const vk::DeviceInterface& vk = m_context.getDeviceInterface();
    604 		vk.destroyQueryPool(device, m_queryPool, /*pAllocator*/ DE_NULL);
    605 	}
    606 }
    607 
    608 tcu::TestStatus OcclusionQueryTestInstance::iterate (void)
    609 {
    610 	const vk::VkQueue			queue		= m_context.getUniversalQueue();
    611 	const vk::DeviceInterface&	vk			= m_context.getDeviceInterface();
    612 	tcu::TestLog&				log			= m_context.getTestContext().getLog();
    613 	std::vector<tcu::Vec4>		vertices	(NUM_VERTICES);
    614 
    615 	// 1st triangle
    616 	vertices[START_VERTEX + 0] = tcu::Vec4( 0.5,  0.5, 0.5, 1.0);
    617 	vertices[START_VERTEX + 1] = tcu::Vec4( 0.5, -0.5, 0.5, 1.0);
    618 	vertices[START_VERTEX + 2] = tcu::Vec4(-0.5,  0.5, 0.5, 1.0);
    619 	// 2nd triangle - partially occluding the scene
    620 	vertices[START_VERTEX_PARTIALLY_OCCLUDED + 0] = tcu::Vec4(-0.5, -0.5, 1.0, 1.0);
    621 	vertices[START_VERTEX_PARTIALLY_OCCLUDED + 1] = tcu::Vec4( 0.5, -0.5, 1.0, 1.0);
    622 	vertices[START_VERTEX_PARTIALLY_OCCLUDED + 2] = tcu::Vec4(-0.5,  0.5, 1.0, 1.0);
    623 	// 3nd triangle - fully occluding the scene
    624 	vertices[START_VERTEX_OCCLUDER + 0] = tcu::Vec4( 0.5,  0.5, 1.0, 1.0);
    625 	vertices[START_VERTEX_OCCLUDER + 1] = tcu::Vec4( 0.5, -0.5, 1.0, 1.0);
    626 	vertices[START_VERTEX_OCCLUDER + 2] = tcu::Vec4(-0.5,  0.5, 1.0, 1.0);
    627 
    628 	m_stateObjects->setVertices(vk, vertices);
    629 
    630 	{
    631 		const vk::VkSubmitInfo submitInfo =
    632 		{
    633 			vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
    634 			DE_NULL,							// const void*				pNext;
    635 			0,									// deUint32					waitSemaphoreCount;
    636 			DE_NULL,							// const VkSemaphore*		pWaitSemaphores;
    637 			(const vk::VkPipelineStageFlags*)DE_NULL,
    638 			1,									// deUint32					commandBufferCount;
    639 			&m_renderCommandBuffer.get(),		// const VkCommandBuffer*	pCommandBuffers;
    640 			0,									// deUint32					signalSemaphoreCount;
    641 			DE_NULL								// const VkSemaphore*		pSignalSemaphores;
    642 		};
    643 		vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
    644 	}
    645 
    646 	if (m_testVector.queryWait == WAIT_QUEUE)
    647 	{
    648 		VK_CHECK(vk.queueWaitIdle(queue));
    649 
    650 		if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
    651 		{
    652 			// In case of WAIT_QUEUE test variant, the previously submitted m_renderCommandBuffer did not
    653 			// contain vkCmdCopyQueryResults, so additional cmd buffer is needed.
    654 
    655 			// In the case of WAIT_NONE or WAIT_QUERY, vkCmdCopyQueryResults is stored in m_renderCommandBuffer.
    656 
    657 			const vk::VkSubmitInfo submitInfo =
    658 			{
    659 				vk::VK_STRUCTURE_TYPE_SUBMIT_INFO,	// VkStructureType			sType;
    660 				DE_NULL,							// const void*				pNext;
    661 				0,									// deUint32					waitSemaphoreCount;
    662 				DE_NULL,							// const VkSemaphore*		pWaitSemaphores;
    663 				(const vk::VkPipelineStageFlags*)DE_NULL,
    664 				1,									// deUint32					commandBufferCount;
    665 				&m_copyResultsCommandBuffer.get(),	// const VkCommandBuffer*	pCommandBuffers;
    666 				0,									// deUint32					signalSemaphoreCount;
    667 				DE_NULL								// const VkSemaphore*		pSignalSemaphores;
    668 			};
    669 			vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
    670 		}
    671 	}
    672 
    673 	if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
    674 	{
    675 		// In case of vkCmdCopyQueryResults is used, test must always wait for it
    676 		// to complete before we can read the result buffer.
    677 
    678 		VK_CHECK(vk.queueWaitIdle(queue));
    679 	}
    680 
    681 	deUint64 queryResults		[NUM_QUERIES_IN_POOL];
    682 	deUint64 queryAvailability	[NUM_QUERIES_IN_POOL];
    683 
    684 	// Allow not ready results only if nobody waited before getting the query results
    685 	bool	allowNotReady		= (m_testVector.queryWait == WAIT_NONE);
    686 
    687 	captureResults(queryResults, queryAvailability, allowNotReady);
    688 
    689 	log << tcu::TestLog::Section("OcclusionQueryResults", "Occlusion query results");
    690 
    691 	logResults(queryResults, queryAvailability);
    692 	bool passed = validateResults(queryResults, queryAvailability, allowNotReady, m_testVector.primitiveTopology);
    693 
    694 	log << tcu::TestLog::EndSection;
    695 
    696 	if (m_testVector.queryResultsMode != RESULTS_MODE_COPY)
    697 	{
    698 		VK_CHECK(vk.queueWaitIdle(queue));
    699 	}
    700 
    701 		if (passed)
    702 	{
    703 		return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed");
    704 	}
    705 	return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed");
    706 }
    707 
    708 vk::Move<vk::VkCommandBuffer> OcclusionQueryTestInstance::recordRender (vk::VkCommandPool cmdPool)
    709 {
    710 	const vk::VkDevice				device		= m_context.getDevice();
    711 	const vk::DeviceInterface&		vk			= m_context.getDeviceInterface();
    712 
    713 	const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
    714 	{
    715 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
    716 		DE_NULL,											// const void*				pNext;
    717 		cmdPool,											// VkCommandPool			commandPool;
    718 		vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
    719 		1u,													// deUint32					bufferCount;
    720 	};
    721 	vk::Move<vk::VkCommandBuffer>	cmdBuffer	(vk::allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo));
    722 	CmdBufferBeginInfo				beginInfo	(0u);
    723 
    724 	vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
    725 
    726 	transition2DImage(vk, *cmdBuffer, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL, 0, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
    727 	transition2DImage(vk, *cmdBuffer, m_stateObjects->m_DepthImage->object(), vk::VK_IMAGE_ASPECT_DEPTH_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 0, vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT);
    728 
    729 	std::vector<vk::VkClearValue>	renderPassClearValues(2);
    730 	deMemset(&renderPassClearValues[0], 0, static_cast<int>(renderPassClearValues.size()) * sizeof(vk::VkClearValue));
    731 
    732 	const vk::VkRect2D renderArea =
    733 	{
    734 		{ 0,					0 },
    735 		{ StateObjects::WIDTH,	StateObjects::HEIGHT }
    736 	};
    737 
    738 	RenderPassBeginInfo renderPassBegin(*m_stateObjects->m_renderPass, *m_stateObjects->m_framebuffer, renderArea, renderPassClearValues);
    739 
    740 	vk.cmdResetQueryPool(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL);
    741 
    742 	vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBegin, vk::VK_SUBPASS_CONTENTS_INLINE);
    743 
    744 	vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS,	*m_stateObjects->m_pipeline);
    745 
    746 	vk::VkBuffer vertexBuffer = m_stateObjects->m_vertexBuffer->object();
    747 	const vk::VkDeviceSize vertexBufferOffset = 0;
    748 	vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
    749 
    750 	// Draw un-occluded geometry
    751 	vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_ALL, m_testVector.queryControlFlags);
    752 	vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, START_VERTEX, 0);
    753 	vk.cmdEndQuery(*cmdBuffer, m_queryPool,	QUERY_INDEX_CAPTURE_ALL);
    754 
    755 	// Partially occlude geometry
    756 	vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL, 1, START_VERTEX_PARTIALLY_OCCLUDED, 0);
    757 
    758 	// Draw partially-occluded geometry
    759 	vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED, m_testVector.queryControlFlags);
    760 	vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, START_VERTEX, 0);
    761 	vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED);
    762 
    763 	// Occlude geometry
    764 	vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_OCCLUDER_DRAWCALL, 1, START_VERTEX_OCCLUDER, 0);
    765 
    766 	// Draw occluded geometry
    767 	vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_OCCLUDED, m_testVector.queryControlFlags);
    768 	vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, START_VERTEX, 0);
    769 	vk.cmdEndQuery(*cmdBuffer, m_queryPool,	QUERY_INDEX_CAPTURE_OCCLUDED);
    770 
    771 	vk.cmdEndRenderPass(*cmdBuffer);
    772 
    773 	if (m_testVector.queryWait != WAIT_QUEUE )
    774 	{
    775 		//For WAIT_QUEUE another cmdBuffer is issued with cmdCopyQueryPoolResults
    776 		if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
    777 		{
    778 			vk.cmdCopyQueryPoolResults(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL, m_queryPoolResultsBuffer->object(), /*dstOffset*/ 0, m_testVector.queryResultsStride, m_queryResultFlags);
    779 		}
    780 	}
    781 
    782 	transition2DImage(vk, *cmdBuffer, m_stateObjects->m_colorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT);
    783 
    784 	vk.endCommandBuffer(*cmdBuffer);
    785 
    786 	return cmdBuffer;
    787 }
    788 
    789 vk::Move<vk::VkCommandBuffer> OcclusionQueryTestInstance::recordCopyResults (vk::VkCommandPool cmdPool)
    790 {
    791 	const vk::VkDevice				device		= m_context.getDevice();
    792 	const vk::DeviceInterface&		vk			= m_context.getDeviceInterface();
    793 
    794 	const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
    795 	{
    796 		vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,	// VkStructureType			sType;
    797 		DE_NULL,											// const void*				pNext;
    798 		cmdPool,											// VkCommandPool			commandPool;
    799 		vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY,				// VkCommandBufferLevel		level;
    800 		1u,													// deUint32					bufferCount;
    801 	};
    802 	vk::Move<vk::VkCommandBuffer>	cmdBuffer	(vk::allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo));
    803 	const CmdBufferBeginInfo		beginInfo	(0u);
    804 
    805 	vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
    806 	vk.cmdCopyQueryPoolResults(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL, m_queryPoolResultsBuffer->object(), /*dstOffset*/ 0, m_testVector.queryResultsStride, m_queryResultFlags);
    807 	vk.endCommandBuffer(*cmdBuffer);
    808 
    809 	return cmdBuffer;
    810 }
    811 
    812 void OcclusionQueryTestInstance::captureResults (deUint64* retResults, deUint64* retAvailAbility, bool allowNotReady)
    813 {
    814 
    815 	const vk::VkDevice			device			= m_context.getDevice();
    816 	const vk::DeviceInterface&	vk				= m_context.getDeviceInterface();
    817 	std::vector<deUint8>		resultsBuffer	(static_cast<size_t>(m_testVector.queryResultsStride) * NUM_QUERIES_IN_POOL);
    818 
    819 	if (m_testVector.queryResultsMode == RESULTS_MODE_GET)
    820 	{
    821 		const vk::VkResult queryResult = vk.getQueryPoolResults(device, m_queryPool, 0, NUM_QUERIES_IN_POOL, resultsBuffer.size(), &resultsBuffer[0], m_testVector.queryResultsStride, m_queryResultFlags);
    822 		if (queryResult == vk::VK_NOT_READY && !allowNotReady)
    823 		{
    824 			TCU_FAIL("getQueryPoolResults returned VK_NOT_READY, but results should be already available.");
    825 		}
    826 		else
    827 		{
    828 			VK_CHECK(queryResult);
    829 		}
    830 	}
    831 	else if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
    832 	{
    833 		const vk::Allocation& allocation = m_queryPoolResultsBuffer->getBoundMemory();
    834 		const void* allocationData = allocation.getHostPtr();
    835 
    836 		vk::invalidateMappedMemoryRange(vk, device, allocation.getMemory(), allocation.getOffset(), resultsBuffer.size());
    837 
    838 		deMemcpy(&resultsBuffer[0], allocationData, resultsBuffer.size());
    839 	}
    840 
    841 	for (int queryNdx = 0; queryNdx < NUM_QUERIES_IN_POOL; queryNdx++)
    842 	{
    843 		const void* srcPtr = &resultsBuffer[queryNdx * static_cast<size_t>(m_testVector.queryResultsStride)];
    844 		if (m_testVector.queryResultSize == RESULT_SIZE_32_BIT)
    845 		{
    846 			const deUint32* srcPtrTyped = static_cast<const deUint32*>(srcPtr);
    847 			retResults[queryNdx]		= *srcPtrTyped;
    848 			if (m_testVector.queryResultsAvailability)
    849 			{
    850 				retAvailAbility[queryNdx] = *(srcPtrTyped + 1);
    851 			}
    852 		}
    853 		else if (m_testVector.queryResultSize == RESULT_SIZE_64_BIT)
    854 		{
    855 			const deUint64* srcPtrTyped = static_cast<const deUint64*>(srcPtr);
    856 			retResults[queryNdx]		= *srcPtrTyped;
    857 
    858 			if (m_testVector.queryResultsAvailability)
    859 			{
    860 				if (m_testVector.queryResultsAvailability)
    861 				{
    862 					retAvailAbility[queryNdx] = *(srcPtrTyped + 1);
    863 				}
    864 			}
    865 		}
    866 		else
    867 		{
    868 			TCU_FAIL("Wrong m_testVector.queryResultSize");
    869 		}
    870 	}
    871 }
    872 
    873 void OcclusionQueryTestInstance::logResults (const deUint64* results, const deUint64* availability)
    874 {
    875 	tcu::TestLog& log = m_context.getTestContext().getLog();
    876 
    877 	for (int ndx = 0; ndx < NUM_QUERIES_IN_POOL; ++ndx)
    878 	{
    879 		if (!m_testVector.queryResultsAvailability)
    880 		{
    881 			log << tcu::TestLog::Message << "query[ slot == " << ndx << "] result == " << results[ndx] << tcu::TestLog::EndMessage;
    882 		}
    883 		else
    884 		{
    885 			log << tcu::TestLog::Message << "query[ slot == " << ndx << "] result == " << results[ndx] << ", availability	== " << availability[ndx] << tcu::TestLog::EndMessage;
    886 		}
    887 	}
    888 }
    889 
    890 bool OcclusionQueryTestInstance::validateResults (const deUint64* results , const deUint64* availability, bool allowUnavailable, vk::VkPrimitiveTopology primitiveTopology)
    891 {
    892 	bool passed			= true;
    893 	tcu::TestLog& log	= m_context.getTestContext().getLog();
    894 
    895 	for (int queryNdx = 0; queryNdx < NUM_QUERIES_IN_POOL; ++queryNdx)
    896 	{
    897 		deUint64 expectedValueMin = 0;
    898 		deUint64 expectedValueMax = 0;
    899 
    900 		if (m_testVector.queryResultsAvailability && availability[queryNdx] == 0)
    901 		{
    902 			// query result was not available
    903 			if (!allowUnavailable)
    904 			{
    905 				log << tcu::TestLog::Message << "query results availability was 0 for index "
    906 					<< queryNdx << ", expected any value greater than 0." << tcu::TestLog::EndMessage;
    907 				passed = false;
    908 				continue;
    909 			}
    910 		}
    911 		else
    912 		{
    913 			// query is available, so expect proper result values
    914 			if (primitiveTopology == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
    915 			{
    916 				switch (queryNdx)
    917 				{
    918 					case QUERY_INDEX_CAPTURE_OCCLUDED:
    919 						expectedValueMin = 0;
    920 						expectedValueMax = 0;
    921 						break;
    922 					case QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED:
    923 						expectedValueMin = 1;
    924 						expectedValueMax = 1;
    925 						break;
    926 					case QUERY_INDEX_CAPTURE_ALL:
    927 						expectedValueMin = NUM_VERTICES_IN_DRAWCALL;
    928 						expectedValueMax = NUM_VERTICES_IN_DRAWCALL;
    929 						break;
    930 				}
    931 			}
    932 			else if (primitiveTopology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
    933 			{
    934 				switch (queryNdx)
    935 				{
    936 					case QUERY_INDEX_CAPTURE_OCCLUDED:
    937 						expectedValueMin = 0;
    938 						expectedValueMax = 0;
    939 						break;
    940 					case QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED:
    941 					case QUERY_INDEX_CAPTURE_ALL:
    942 						{
    943 							const int primWidth		= StateObjects::WIDTH  / 2;
    944 							const int primHeight	= StateObjects::HEIGHT / 2;
    945 							const int primArea		= primWidth * primHeight / 2;
    946 							expectedValueMin		= (int)(0.97f * primArea);
    947 							expectedValueMax		= (int)(1.03f * primArea);
    948 						}
    949 				}
    950 			}
    951 			else
    952 			{
    953 				TCU_FAIL("Unsupported primitive topology");
    954 			}
    955 		}
    956 
    957 		if ((m_testVector.queryControlFlags & vk::VK_QUERY_CONTROL_PRECISE_BIT) || (expectedValueMin == 0 && expectedValueMax == 0))
    958 		{
    959 			// require precise value
    960 			if (results[queryNdx] < expectedValueMin || results[queryNdx] > expectedValueMax)
    961 			{
    962 				log << tcu::TestLog::Message << "wrong value of query for index "
    963 					<< queryNdx << ", expected the value minimum of " << expectedValueMin << ", maximum of " << expectedValueMax << " got "
    964 					<< results[queryNdx] << "." << tcu::TestLog::EndMessage;
    965 				passed = false;
    966 			}
    967 		}
    968 		else
    969 		{
    970 			// require imprecise value greater than 0
    971 			if (results[queryNdx] == 0)
    972 			{
    973 				log << tcu::TestLog::Message << "wrong value of query for index "
    974 					<< queryNdx << ", expected any non-zero value, got "
    975 					<< results[queryNdx] << "." << tcu::TestLog::EndMessage;
    976 				passed = false;
    977 			}
    978 		}
    979 	}
    980 	return passed;
    981 }
    982 
    983 template<class Instance>
    984 class QueryPoolOcclusionTest : public vkt::TestCase
    985 {
    986 public:
    987 	QueryPoolOcclusionTest (tcu::TestContext &context, const char *name, const char *description, const OcclusionQueryTestVector& testVector)
    988 		: TestCase			(context, name, description)
    989 		, m_testVector		(testVector)
    990 	{
    991 	}
    992 private:
    993 	vkt::TestInstance* createInstance (vkt::Context& context) const
    994 	{
    995 		return new Instance(context, m_testVector);
    996 	}
    997 
    998 	void initPrograms(vk::SourceCollections& programCollection) const
    999 	{
   1000 		programCollection.glslSources.add("frag") << glu::FragmentSource("#version 400\n"
   1001 																	   "layout(location = 0) out vec4 out_FragColor;\n"
   1002 																	   "void main()\n"
   1003 																	   "{\n"
   1004 																	   "	out_FragColor = vec4(0.07, 0.48, 0.75, 1.0);\n"
   1005 																	   "}\n");
   1006 
   1007 		programCollection.glslSources.add("vert") << glu::VertexSource("#version 430\n"
   1008 																		 "layout(location = 0) in vec4 in_Postion;\n"
   1009 																		 "void main() {\n"
   1010 																		 "	gl_Position  = in_Postion;\n"
   1011 																		 "	gl_PointSize = 1.0;\n"
   1012 																		 "}\n");
   1013 	}
   1014 
   1015 	OcclusionQueryTestVector m_testVector;
   1016 };
   1017 
   1018 } //anonymous
   1019 
   1020 namespace vkt
   1021 {
   1022 
   1023 namespace QueryPool
   1024 {
   1025 
   1026 QueryPoolOcclusionTests::QueryPoolOcclusionTests (tcu::TestContext &testCtx)
   1027 	: TestCaseGroup(testCtx, "occlusion_query", "Tests for occlusion queries")
   1028 {
   1029 	/* Left blank on purpose */
   1030 }
   1031 
   1032 QueryPoolOcclusionTests::~QueryPoolOcclusionTests (void)
   1033 {
   1034 	/* Left blank on purpose */
   1035 }
   1036 
   1037 void QueryPoolOcclusionTests::init (void)
   1038 {
   1039 	OcclusionQueryTestVector baseTestVector;
   1040 	baseTestVector.queryControlFlags		= 0;
   1041 	baseTestVector.queryResultSize			= RESULT_SIZE_64_BIT;
   1042 	baseTestVector.queryWait				= WAIT_QUEUE;
   1043 	baseTestVector.queryResultsMode			= RESULTS_MODE_GET;
   1044 	baseTestVector.queryResultsStride		= sizeof(deUint64);
   1045 	baseTestVector.queryResultsAvailability = false;
   1046 	baseTestVector.primitiveTopology		= vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
   1047 
   1048 	//Basic tests
   1049 	{
   1050 		OcclusionQueryTestVector testVector = baseTestVector;
   1051 		testVector.queryControlFlags = 0;
   1052 		addChild(new QueryPoolOcclusionTest<BasicOcclusionQueryTestInstance>(m_testCtx,	"basic_conservative",	"draw with conservative occlusion query",	testVector));
   1053 		testVector.queryControlFlags = vk::VK_QUERY_CONTROL_PRECISE_BIT;
   1054 		addChild(new QueryPoolOcclusionTest<BasicOcclusionQueryTestInstance>(m_testCtx,	"basic_precise",		"draw with precise occlusion query",		testVector));
   1055 	}
   1056 
   1057 	// Functional test
   1058 	{
   1059 		vk::VkQueryControlFlags	controlFlags[]		= { 0,					vk::VK_QUERY_CONTROL_PRECISE_BIT	};
   1060 		const char*				controlFlagsStr[]	= { "conservative",		"precise"							};
   1061 
   1062 		for (int controlFlagIdx = 0; controlFlagIdx < DE_LENGTH_OF_ARRAY(controlFlags); ++controlFlagIdx)
   1063 		{
   1064 
   1065 			vk::VkPrimitiveTopology	primitiveTopology[]		= { vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST };
   1066 			const char*				primitiveTopologyStr[]	= { "points", "triangles" };
   1067 			for (int primitiveTopologyIdx = 0; primitiveTopologyIdx < DE_LENGTH_OF_ARRAY(primitiveTopology); ++primitiveTopologyIdx)
   1068 			{
   1069 
   1070 				OcclusionQueryResultSize	resultSize[]	= { RESULT_SIZE_32_BIT, RESULT_SIZE_64_BIT };
   1071 				const char*					resultSizeStr[] = { "32",				"64" };
   1072 
   1073 				for (int resultSizeIdx = 0; resultSizeIdx < DE_LENGTH_OF_ARRAY(resultSize); ++resultSizeIdx)
   1074 				{
   1075 
   1076 					OcclusionQueryWait	wait[]		= { WAIT_QUEUE, WAIT_QUERY };
   1077 					const char*			waitStr[]	= { "queue",	"query" };
   1078 
   1079 					for (int waitIdx = 0; waitIdx < DE_LENGTH_OF_ARRAY(wait); ++waitIdx)
   1080 					{
   1081 						OcclusionQueryResultsMode	resultsMode[]		= { RESULTS_MODE_GET,	RESULTS_MODE_COPY };
   1082 						const char*					resultsModeStr[]	= { "get",				"copy" };
   1083 
   1084 						for (int resultsModeIdx = 0; resultsModeIdx < DE_LENGTH_OF_ARRAY(resultsMode); ++resultsModeIdx)
   1085 						{
   1086 
   1087 							bool testAvailability[]				= { false, true };
   1088 							const char* testAvailabilityStr[]	= { "without", "with"};
   1089 
   1090 							for (int testAvailabilityIdx = 0; testAvailabilityIdx < DE_LENGTH_OF_ARRAY(testAvailability); ++testAvailabilityIdx)
   1091 							{
   1092 								OcclusionQueryTestVector testVector			= baseTestVector;
   1093 								testVector.queryControlFlags				= controlFlags[controlFlagIdx];
   1094 								testVector.queryResultSize					= resultSize[resultSizeIdx];
   1095 								testVector.queryWait						= wait[waitIdx];
   1096 								testVector.queryResultsMode					= resultsMode[resultsModeIdx];
   1097 								testVector.queryResultsStride				= (testVector.queryResultSize == RESULT_SIZE_32_BIT ? sizeof(deUint32) : sizeof(deUint64));
   1098 								testVector.queryResultsAvailability			= testAvailability[testAvailabilityIdx];
   1099 								testVector.primitiveTopology				= primitiveTopology[primitiveTopologyIdx];
   1100 
   1101 								if (testVector.queryResultsAvailability)
   1102 								{
   1103 									testVector.queryResultsStride *= 2;
   1104 								}
   1105 
   1106 								std::ostringstream testName;
   1107 								std::ostringstream testDescr;
   1108 
   1109 								testName << resultsModeStr[resultsModeIdx] << "_results"
   1110 										 << "_" << controlFlagsStr[controlFlagIdx]
   1111 										 << "_size_" << resultSizeStr[resultSizeIdx]
   1112 										 << "_wait_" << waitStr[waitIdx]
   1113 										 << "_" << testAvailabilityStr[testAvailabilityIdx] << "_availability"
   1114 										 << "_draw_" <<  primitiveTopologyStr[primitiveTopologyIdx];
   1115 
   1116 								testDescr << "draw occluded " << primitiveTopologyStr[primitiveTopologyIdx]
   1117 										  << "with " << controlFlagsStr[controlFlagIdx] << ", "
   1118 									      << resultsModeStr[resultsModeIdx] << " results "
   1119 									      << testAvailabilityStr[testAvailabilityIdx] << " availability bit as "
   1120 										  << resultSizeStr[resultSizeIdx] << "bit variables,"
   1121 									      << "wait for results on" << waitStr[waitIdx];
   1122 
   1123 								addChild(new QueryPoolOcclusionTest<OcclusionQueryTestInstance>(m_testCtx, testName.str().c_str(), testDescr.str().c_str(), testVector));
   1124 							}
   1125 						}
   1126 					}
   1127 				}
   1128 			}
   1129 		}
   1130 	}
   1131 	// Test different strides
   1132 	{
   1133 		OcclusionQueryResultsMode	resultsMode[]		= { RESULTS_MODE_GET,	RESULTS_MODE_COPY	};
   1134 		const char*					resultsModeStr[]	= { "get",				"copy"				};
   1135 
   1136 		for (int resultsModeIdx = 0; resultsModeIdx < DE_LENGTH_OF_ARRAY(resultsMode); ++resultsModeIdx)
   1137 		{
   1138 			OcclusionQueryResultSize	resultSizes[]	= { RESULT_SIZE_32_BIT, RESULT_SIZE_64_BIT };
   1139 			const char*					resultSizeStr[] = { "32", "64" };
   1140 
   1141 			bool testAvailability[]				= { false,		true	};
   1142 			const char* testAvailabilityStr[]	= { "without",	"with"	};
   1143 
   1144 			for (int testAvailabilityIdx = 0; testAvailabilityIdx < DE_LENGTH_OF_ARRAY(testAvailability); ++testAvailabilityIdx)
   1145 			{
   1146 				for (int resultSizeIdx = 0; resultSizeIdx < DE_LENGTH_OF_ARRAY(resultSizes); ++resultSizeIdx)
   1147 				{
   1148 					const vk::VkDeviceSize resultSize	= (resultSizes[resultSizeIdx] == RESULT_SIZE_32_BIT ? sizeof(deUint32) : sizeof(deUint64));
   1149 
   1150 					// \todo [2015-12-18 scygan] Ensure only stride values aligned to resultSize are allowed. Otherwise test should be extended.
   1151 					const vk::VkDeviceSize strides[]	=
   1152 					{
   1153 						1 * resultSize,
   1154 						2 * resultSize,
   1155 						3 * resultSize,
   1156 						4 * resultSize,
   1157 						5 * resultSize,
   1158 						13 * resultSize,
   1159 						1024 * resultSize
   1160 					};
   1161 
   1162 					for (int strideIdx = 0; strideIdx < DE_LENGTH_OF_ARRAY(strides); strideIdx++)
   1163 					{
   1164 						OcclusionQueryTestVector testVector		= baseTestVector;
   1165 						testVector.queryResultsMode				= resultsMode[resultsModeIdx];
   1166 						testVector.queryResultSize				= resultSizes[resultSizeIdx];
   1167 						testVector.queryResultsAvailability		= testAvailability[testAvailabilityIdx];
   1168 						testVector.queryResultsStride			= strides[strideIdx];
   1169 
   1170 						const vk::VkDeviceSize elementSize		= (testVector.queryResultsAvailability ? resultSize * 2 : resultSize);
   1171 
   1172 						if (elementSize > testVector.queryResultsStride)
   1173 						{
   1174 							continue;
   1175 						}
   1176 
   1177 						std::ostringstream testName;
   1178 						std::ostringstream testDescr;
   1179 
   1180 						testName << resultsModeStr[resultsModeIdx]
   1181 								 << "_results_size_" << resultSizeStr[resultSizeIdx]
   1182 								 << "_stride_" << strides[strideIdx]
   1183 								 << "_" << testAvailabilityStr[testAvailabilityIdx] << "_availability";
   1184 
   1185 						testDescr << resultsModeStr[resultsModeIdx] << " results "
   1186 								  << testAvailabilityStr[testAvailabilityIdx] << " availability bit as "
   1187 								  << resultSizeStr[resultSizeIdx] << "bit variables, with stride" << strides[strideIdx];
   1188 
   1189 						addChild(new QueryPoolOcclusionTest<OcclusionQueryTestInstance>(m_testCtx, testName.str().c_str(), testDescr.str().c_str(), testVector));
   1190 					}
   1191 				}
   1192 			}
   1193 		}
   1194 
   1195 	}
   1196 }
   1197 
   1198 } //QueryPool
   1199 } //vkt
   1200 
   1201