1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Intel Corporation
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and/or associated documentation files (the
10 * "Materials"), to deal in the Materials without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Materials, and to
13 * permit persons to whom the Materials are furnished to do so, subject to
14 * the following conditions:
16 * The above copyright notice(s) and this permission notice shall be included
17 * in all copies or substantial portions of the Materials.
19 * The Materials are Confidential Information as defined by the
20 * Khronos Membership Agreement until designated non-confidential by Khronos,
21 * at which point this condition clause shall be removed.
23 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 * MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
33 * \brief Vulkan Occlusion Query Tests
34 *//*--------------------------------------------------------------------*/
36 #include "vktQueryPoolOcclusionTests.hpp"
38 #include "vktTestCase.hpp"
40 #include "vktQueryPoolImageObjectUtil.hpp"
41 #include "vktQueryPoolBufferObjectUtil.hpp"
42 #include "vktQueryPoolCreateInfoUtil.hpp"
43 #include "vkBuilderUtil.hpp"
44 #include "vkRefUtil.hpp"
45 #include "vkPrograms.hpp"
47 #include "tcuTestLog.hpp"
48 #include "tcuResource.hpp"
49 #include "tcuImageCompare.hpp"
50 #include "tcuCommandLine.hpp"
52 using namespace vkt::QueryPool;
58 StateObjects (const vk::DeviceInterface&vk, vkt::Context &context, const int numVertices, vk::VkPrimitiveTopology primitive);
59 void setVertices (const vk::DeviceInterface&vk, std::vector<tcu::Vec4> vertices);
67 vkt::Context &m_context;
69 vk::Move<vk::VkPipeline> m_Pipeline;
70 vk::Move<vk::VkPipelineLayout> m_PipelineLayout;
72 de::SharedPtr<Image> m_ColorAttachmentImage, m_DepthImage;
73 vk::Move<vk::VkImageView> m_AttachmentView;
74 vk::Move<vk::VkImageView> m_DepthView;
76 vk::Move<vk::VkRenderPass> m_RenderPass;
77 vk::Move<vk::VkFramebuffer> m_Framebuffer;
79 de::SharedPtr<Buffer> m_VertexBuffer;
81 vk::VkFormat m_ColorAttachmentFormat;
84 StateObjects::StateObjects (const vk::DeviceInterface&vk, vkt::Context &context, const int numVertices, vk::VkPrimitiveTopology primitive)
86 , m_ColorAttachmentFormat(vk::VK_FORMAT_R8G8B8A8_UNORM)
89 vk::VkFormat depthFormat = vk::VK_FORMAT_D16_UNORM;
90 const vk::VkDevice device = m_context.getDevice();
92 //attachment images and views
94 vk::VkExtent3D imageExtent =
101 const ImageCreateInfo colorImageCreateInfo(vk::VK_IMAGE_TYPE_2D, m_ColorAttachmentFormat, imageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL,
102 vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
104 m_ColorAttachmentImage = Image::createAndAlloc(vk, device, colorImageCreateInfo, m_context.getDefaultAllocator());
106 const ImageViewCreateInfo attachmentViewInfo(m_ColorAttachmentImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_ColorAttachmentFormat);
107 m_AttachmentView = vk::createImageView(vk, device, &attachmentViewInfo);
109 ImageCreateInfo depthImageCreateInfo(vk::VK_IMAGE_TYPE_2D, depthFormat, imageExtent, 1, 1, vk::VK_SAMPLE_COUNT_1_BIT, vk::VK_IMAGE_TILING_OPTIMAL,
110 vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
112 m_DepthImage = Image::createAndAlloc(vk, device, depthImageCreateInfo, m_context.getDefaultAllocator());
114 // Construct a depth view from depth image
115 const ImageViewCreateInfo depthViewInfo(m_DepthImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, depthFormat);
116 m_DepthView = vk::createImageView(vk, device, &depthViewInfo);
120 // Renderpass and Framebuffer
122 RenderPassCreateInfo renderPassCreateInfo;
123 renderPassCreateInfo.addAttachment(AttachmentDescription(m_ColorAttachmentFormat, // format
124 vk::VK_SAMPLE_COUNT_1_BIT, // samples
125 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // loadOp
126 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // storeOp
127 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
128 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilLoadOp
129 vk::VK_IMAGE_LAYOUT_GENERAL, // initialLauout
130 vk::VK_IMAGE_LAYOUT_GENERAL)); // finalLayout
132 renderPassCreateInfo.addAttachment(AttachmentDescription(depthFormat, // format
133 vk::VK_SAMPLE_COUNT_1_BIT, // samples
134 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // loadOp
135 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // storeOp
136 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // stencilLoadOp
137 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // stencilLoadOp
138 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // initialLauout
139 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)); // finalLayout
141 const vk::VkAttachmentReference colorAttachmentReference =
144 vk::VK_IMAGE_LAYOUT_GENERAL // layout
147 const vk::VkAttachmentReference depthAttachmentReference =
150 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // layout
153 renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
156 DE_NULL, // pInputAttachments
158 &colorAttachmentReference, // pColorAttachments
159 DE_NULL, // pResolveAttachments
160 depthAttachmentReference, // depthStencilAttachment
162 DE_NULL)); // preserveAttachments
164 m_RenderPass = vk::createRenderPass(vk, device, &renderPassCreateInfo);
166 std::vector<vk::VkImageView> attachments(2);
167 attachments[0] = *m_AttachmentView;
168 attachments[1] = *m_DepthView;
170 FramebufferCreateInfo framebufferCreateInfo(*m_RenderPass, attachments, WIDTH, HEIGHT, 1);
171 m_Framebuffer = vk::createFramebuffer(vk, device, &framebufferCreateInfo);
177 vk::Unique<vk::VkShaderModule> vs(vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
178 vk::Unique<vk::VkShaderModule> fs(vk::createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
180 const PipelineCreateInfo::ColorBlendState::Attachment attachmentState;
182 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
183 m_PipelineLayout = vk::createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
185 const vk::VkVertexInputBindingDescription vf_binding_desc =
188 4 * sizeof(float), // stride;
189 vk::VK_VERTEX_INPUT_RATE_VERTEX // inputRate
192 const vk::VkVertexInputAttributeDescription vf_attribute_desc =
196 vk::VK_FORMAT_R32G32B32A32_SFLOAT, // format;
200 const vk::VkPipelineVertexInputStateCreateInfo vf_info =
202 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // pNext;
204 0u, // vertexBindingDescriptionCount;
205 1, // pVertexBindingDescriptions;
206 &vf_binding_desc, // vertexAttributeDescriptionCount;
207 1, // pVertexAttributeDescriptions;
211 PipelineCreateInfo pipelineCreateInfo(*m_PipelineLayout, *m_RenderPass, 0, 0);
212 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
213 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
214 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(primitive));
215 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &attachmentState));
216 const vk::VkViewport viewport =
220 WIDTH, // float width;
221 HEIGHT, // float height;
222 0.0f, // float minDepth;
223 1.0f // float maxDepth;
226 const vk::VkRect2D scissor =
231 }, // VkOffset2D offset;
233 WIDTH, // deInt32 width;
234 HEIGHT, // deInt32 height
235 }, // VkExtent2D extent;
237 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport), std::vector<vk::VkRect2D>(1, scissor)));
238 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState(true, true, vk::VK_COMPARE_OP_GREATER_OR_EQUAL));
239 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
240 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState());
241 pipelineCreateInfo.addState(vf_info);
242 m_Pipeline = vk::createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
247 const size_t kBufferSize = numVertices * sizeof(tcu::Vec4);
248 m_VertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(kBufferSize, vk::VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
252 void StateObjects::setVertices (const vk::DeviceInterface&vk, std::vector<tcu::Vec4> vertices)
254 const vk::VkDevice device = m_context.getDevice();
256 tcu::Vec4 *ptr = reinterpret_cast<tcu::Vec4*>(m_VertexBuffer->getBoundMemory().getHostPtr());
257 std::copy(vertices.begin(), vertices.end(), ptr);
259 vk::flushMappedMemoryRange(vk, device, m_VertexBuffer->getBoundMemory().getMemory(), m_VertexBuffer->getBoundMemory().getOffset(), vertices.size() * sizeof(vertices[0]));
262 enum OcclusionQueryResultSize
268 enum OcclusionQueryWait
275 enum OcclusionQueryResultsMode
281 struct OcclusionQueryTestVector
283 vk::VkQueryControlFlags queryControlFlags;
284 OcclusionQueryResultSize queryResultSize;
285 OcclusionQueryWait queryWait;
286 OcclusionQueryResultsMode queryResultsMode;
287 vk::VkDeviceSize queryResultsStride;
288 bool queryResultsAvailability;
289 vk::VkPrimitiveTopology primitiveRopology;
292 class BasicOcclusionQueryTestInstance : public vkt::TestInstance
295 BasicOcclusionQueryTestInstance (vkt::Context &context, const OcclusionQueryTestVector& testVector);
296 ~BasicOcclusionQueryTestInstance (void);
298 tcu::TestStatus iterate (void);
302 NUM_QUERIES_IN_POOL = 2,
\r
303 QUERY_INDEX_CAPTURE_EMPTY = 0,
\r
304 QUERY_INDEX_CAPTURE_DRAWCALL = 1,
\r
305 NUM_VERTICES_IN_DRAWCALL = 3
308 OcclusionQueryTestVector m_testVector;
309 StateObjects* m_stateObjects;
310 vk::VkQueryPool m_queryPool;
313 BasicOcclusionQueryTestInstance::BasicOcclusionQueryTestInstance (vkt::Context &context, const OcclusionQueryTestVector& testVector)
314 : TestInstance (context)
315 , m_testVector (testVector)
316 , m_stateObjects (new StateObjects(m_context.getDeviceInterface(), m_context, NUM_VERTICES_IN_DRAWCALL, m_testVector.primitiveRopology))
318 DE_ASSERT(testVector.queryResultSize == RESULT_SIZE_64_BIT
319 && testVector.queryWait == WAIT_QUEUE
320 && testVector.queryResultsMode == RESULTS_MODE_GET
321 && testVector.queryResultsStride == sizeof(deUint64)
322 && testVector.queryResultsAvailability == false
323 && testVector.primitiveRopology == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
325 tcu::TestLog& log = m_context.getTestContext().getLog();
326 const vk::VkDevice device = m_context.getDevice();
327 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
329 const vk::VkQueryPoolCreateInfo queryPoolCreateInfo =
331 vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
334 vk::VK_QUERY_TYPE_OCCLUSION,
338 VK_CHECK(vk.createQueryPool(device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL, &m_queryPool));
340 std::vector<tcu::Vec4> vertices(NUM_VERTICES_IN_DRAWCALL);
341 vertices[0] = tcu::Vec4(0.5, 0.5, 0.0, 1.0);
342 vertices[1] = tcu::Vec4(0.5, 0.0, 0.0, 1.0);
343 vertices[2] = tcu::Vec4(0.0, 0.5, 0.0, 1.0);
344 m_stateObjects->setVertices(vk, vertices);
347 BasicOcclusionQueryTestInstance::~BasicOcclusionQueryTestInstance (void)
350 delete m_stateObjects;
352 if (m_queryPool != DE_NULL)
354 const vk::VkDevice device = m_context.getDevice();
355 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
357 vk.destroyQueryPool(device, m_queryPool, /*pAllocator*/ DE_NULL);
361 tcu::TestStatus BasicOcclusionQueryTestInstance::iterate (void)
363 tcu::TestLog &log = m_context.getTestContext().getLog();
364 const vk::VkDevice device = m_context.getDevice();
365 const vk::VkQueue queue = m_context.getUniversalQueue();
366 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
368 const CmdPoolCreateInfo cmdPoolCreateInfo (m_context.getUniversalQueueFamilyIndex());
369 vk::Move<vk::VkCommandPool> cmdPool = vk::createCommandPool(vk, device, &cmdPoolCreateInfo);
371 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
373 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
374 DE_NULL, // const void* pNext;
375 *cmdPool, // VkCommandPool commandPool;
376 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
377 1u, // deUint32 bufferCount;
379 vk::Unique<vk::VkCommandBuffer> cmdBuffer (vk::allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo));
380 const CmdBufferBeginInfo beginInfo (DE_NULL, 0, DE_NULL, 0u, true, m_testVector.queryControlFlags);
382 vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
384 transition2DImage(vk, *cmdBuffer, m_stateObjects->m_ColorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
385 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);
387 std::vector<vk::VkClearValue> renderPassClearValues(2);
388 deMemset(&renderPassClearValues[0], static_cast<int>(renderPassClearValues.size()) * sizeof(vk::VkClearValue), 0);
390 const vk::VkRect2D renderArea =
393 { StateObjects::WIDTH, StateObjects::HEIGHT }
396 RenderPassBeginInfo renderPassBegin(*m_stateObjects->m_RenderPass, *m_stateObjects->m_Framebuffer, renderArea, renderPassClearValues);
398 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBegin, vk::VK_SUBPASS_CONTENTS_INLINE);
400 vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stateObjects->m_Pipeline);
402 vk::VkBuffer vertexBuffer = m_stateObjects->m_VertexBuffer->object();
403 const vk::VkDeviceSize vertexBufferOffset = 0;
404 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
406 vk.cmdResetQueryPool(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL);
408 vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_EMPTY, m_testVector.queryControlFlags);
409 vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_EMPTY);
411 vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_DRAWCALL, m_testVector.queryControlFlags);
412 vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, 0, 0);
413 vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_DRAWCALL);
415 vk.cmdEndRenderPass(*cmdBuffer);
417 transition2DImage(vk, *cmdBuffer, m_stateObjects->m_ColorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
419 vk.endCommandBuffer(*cmdBuffer);
421 // Submit command buffer
422 const vk::VkSubmitInfo submitInfo =
424 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
425 DE_NULL, // const void* pNext;
426 0, // deUint32 waitSemaphoreCount;
427 DE_NULL, // const VkSemaphore* pWaitSemaphores;
428 1, // deUint32 commandBufferCount;
429 &cmdBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
430 0, // deUint32 signalSemaphoreCount;
431 DE_NULL // const VkSemaphore* pSignalSemaphores;
433 vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
435 VK_CHECK(vk.queueWaitIdle(queue));
437 deUint64 queryResults[NUM_QUERIES_IN_POOL] = { 0 };
438 size_t queryResultsSize = sizeof(queryResults);
440 vk::VkResult queryResult = vk.getQueryPoolResults(device, m_queryPool, 0, NUM_QUERIES_IN_POOL, queryResultsSize, queryResults, sizeof(queryResults[0]), vk::VK_QUERY_RESULT_64_BIT);
442 if (queryResult == vk::VK_NOT_READY)
444 TCU_FAIL("Query result not avaliable, but vkWaitIdle() was called.");
447 VK_CHECK(queryResult);
449 log << tcu::TestLog::Section("OcclusionQueryResults",
450 "Occlusion query results");
451 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(queryResults); ++ndx)
453 log << tcu::TestLog::Message << "query[ slot == " << ndx
454 << "] result == " << queryResults[ndx] << tcu::TestLog::EndMessage;
459 for (int queryNdx = 0; queryNdx < DE_LENGTH_OF_ARRAY(queryResults); ++queryNdx)
462 deUint64 expectedValue;
466 case QUERY_INDEX_CAPTURE_EMPTY:
469 case QUERY_INDEX_CAPTURE_DRAWCALL:
470 expectedValue = NUM_VERTICES_IN_DRAWCALL;
474 if ((m_testVector.queryControlFlags & vk::VK_QUERY_CONTROL_PRECISE_BIT) || expectedValue == 0)
476 // require precise value
477 if (queryResults[queryNdx] != expectedValue)
479 log << tcu::TestLog::Message << "vkGetQueryPoolResults returned "
480 "wrong value of query for index "
481 << queryNdx << ", expected " << expectedValue << ", got "
482 << queryResults[0] << "." << tcu::TestLog::EndMessage;
488 // require imprecize value > 0
489 if (queryResults[queryNdx] == 0)
491 log << tcu::TestLog::Message << "vkGetQueryPoolResults returned "
492 "wrong value of query for index "
493 << queryNdx << ", expected any non-zero value, got "
494 << queryResults[0] << "." << tcu::TestLog::EndMessage;
499 log << tcu::TestLog::EndSection;
501 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
503 tcu::ConstPixelBufferAccess resultImageAccess = m_stateObjects->m_ColorAttachmentImage->readSurface(
504 queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_GENERAL,
505 zeroOffset, StateObjects::HEIGHT, StateObjects::WIDTH, vk::VK_IMAGE_ASPECT_COLOR_BIT);
507 log << tcu::TestLog::Image("Result", "Result", resultImageAccess);
511 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed");
513 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed");
516 class OcclusionQueryTestInstance : public vkt::TestInstance
519 OcclusionQueryTestInstance (vkt::Context &context, const OcclusionQueryTestVector& testVector);
520 ~OcclusionQueryTestInstance (void);
522 tcu::TestStatus iterate (void);
524 vk::Move<vk::VkCommandBuffer> recordRender (vk::VkCommandPool commandPool);
525 vk::Move<vk::VkCommandBuffer> recordCopyResults (vk::VkCommandPool commandPool);
527 void captureResults (deUint64* retResults, deUint64* retAvailability, bool allowNotReady);
528 void logResults (const deUint64* results, const deUint64* availability);
529 bool validateResults (const deUint64* results, const deUint64* availability, bool allowUnavailable, vk::VkPrimitiveTopology primitiveTopology);
530 void logRenderTarget (void);
534 NUM_QUERIES_IN_POOL = 3,
\r
535 QUERY_INDEX_CAPTURE_ALL = 0,
\r
536 QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED = 1,
\r
537 QUERY_INDEX_CAPTURE_OCCLUDED = 2
541 NUM_VERTICES_IN_DRAWCALL = 3,
\r
542 NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL = 3,
\r
543 NUM_VERTICES_IN_OCCLUDER_DRAWCALL = 3,
\r
544 NUM_VERTICES = NUM_VERTICES_IN_DRAWCALL + NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL + NUM_VERTICES_IN_OCCLUDER_DRAWCALL
\r
549 START_VERTEX_PARTIALLY_OCCLUDED = START_VERTEX + NUM_VERTICES_IN_DRAWCALL,
\r
550 START_VERTEX_OCCLUDER = START_VERTEX_PARTIALLY_OCCLUDED + NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL
553 OcclusionQueryTestVector m_testVector;
555 const vk::VkQueryResultFlags m_queryResultFlags;
557 StateObjects* m_stateObjects;
558 vk::VkQueryPool m_queryPool;
559 de::SharedPtr<Buffer> m_queryPoolResultsBuffer;
561 vk::Move<vk::VkCommandPool> m_commandPool;
562 vk::Move<vk::VkCommandBuffer> m_renderCommandBuffer;
563 vk::Move<vk::VkCommandBuffer> m_copyResultsCommandBuffer;
566 OcclusionQueryTestInstance::OcclusionQueryTestInstance (vkt::Context &context, const OcclusionQueryTestVector& testVector)
567 : vkt::TestInstance (context)
568 , m_testVector (testVector)
569 , 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.primitiveRopology))
570 , m_queryResultFlags ((m_testVector.queryWait == WAIT_QUERY ? vk::VK_QUERY_RESULT_WAIT_BIT : 0)
571 | (m_testVector.queryResultSize == RESULT_SIZE_64_BIT ? vk::VK_QUERY_RESULT_64_BIT : 0)
572 | (m_testVector.queryResultsAvailability ? vk::VK_QUERY_RESULT_WITH_AVAILABILITY_BIT : 0))
574 const vk::VkDevice device = m_context.getDevice();
575 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
577 const vk::VkQueryPoolCreateInfo queryPoolCreateInfo =
579 vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
582 vk::VK_QUERY_TYPE_OCCLUSION,
587 VK_CHECK(vk.createQueryPool(device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL, &m_queryPool));
589 if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
591 const vk::VkDeviceSize resultsBufferSize = m_testVector.queryResultsStride * NUM_QUERIES_IN_POOL;
592 m_queryPoolResultsBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(resultsBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), m_context.getDefaultAllocator(), vk::MemoryRequirement::HostVisible);
595 const CmdPoolCreateInfo cmdPoolCreateInfo (m_context.getUniversalQueueFamilyIndex());
596 m_commandPool = vk::createCommandPool(vk, device, &cmdPoolCreateInfo);
597 m_renderCommandBuffer = recordRender(*m_commandPool);
599 if (m_testVector.queryWait == WAIT_QUEUE && m_testVector.queryResultsMode == RESULTS_MODE_COPY)
601 m_copyResultsCommandBuffer = recordCopyResults(*m_commandPool);
605 OcclusionQueryTestInstance::~OcclusionQueryTestInstance (void)
607 const vk::VkDevice device = m_context.getDevice();
610 delete m_stateObjects;
612 if (m_queryPool != DE_NULL)
614 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
615 vk.destroyQueryPool(device, m_queryPool, /*pAllocator*/ DE_NULL);
619 tcu::TestStatus OcclusionQueryTestInstance::iterate (void)
621 const vk::VkDevice device = m_context.getDevice();
622 const vk::VkQueue queue = m_context.getUniversalQueue();
623 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
624 tcu::TestLog& log = m_context.getTestContext().getLog();
625 std::vector<tcu::Vec4> vertices (NUM_VERTICES);
628 vertices[START_VERTEX + 0] = tcu::Vec4( 0.5, 0.5, 0.5, 1.0);
629 vertices[START_VERTEX + 1] = tcu::Vec4( 0.5, -0.5, 0.5, 1.0);
630 vertices[START_VERTEX + 2] = tcu::Vec4(-0.5, 0.5, 0.5, 1.0);
631 // 2nd triangle - partially occluding the scene
632 vertices[START_VERTEX_PARTIALLY_OCCLUDED + 0] = tcu::Vec4(-0.5, -0.5, 1.0, 1.0);
633 vertices[START_VERTEX_PARTIALLY_OCCLUDED + 1] = tcu::Vec4( 0.5, -0.5, 1.0, 1.0);
634 vertices[START_VERTEX_PARTIALLY_OCCLUDED + 2] = tcu::Vec4(-0.5, 0.5, 1.0, 1.0);
635 // 3nd triangle - fully occluding the scene
636 vertices[START_VERTEX_OCCLUDER + 0] = tcu::Vec4( 0.5, 0.5, 1.0, 1.0);
637 vertices[START_VERTEX_OCCLUDER + 1] = tcu::Vec4( 0.5, -0.5, 1.0, 1.0);
638 vertices[START_VERTEX_OCCLUDER + 2] = tcu::Vec4(-0.5, 0.5, 1.0, 1.0);
640 m_stateObjects->setVertices(vk, vertices);
642 const vk::VkSubmitInfo submitInfo =
644 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
645 DE_NULL, // const void* pNext;
646 0, // deUint32 waitSemaphoreCount;
647 DE_NULL, // const VkSemaphore* pWaitSemaphores;
648 1, // deUint32 commandBufferCount;
649 &m_renderCommandBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
650 0, // deUint32 signalSemaphoreCount;
651 DE_NULL // const VkSemaphore* pSignalSemaphores;
653 vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
655 if (m_testVector.queryWait == WAIT_QUEUE)
657 VK_CHECK(vk.queueWaitIdle(queue));
659 if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
661 // In case of WAIT_QUEUE test variant, the previously submitted m_renderCommandBuffer did not
662 // contain vkCmdCopyQueryResults, so additional cmd buffer is needed.
664 // In the case of WAIT_NONE or WAIT_QUERY, vkCmdCopyQueryResults is stored in m_renderCommandBuffer.
666 const vk::VkSubmitInfo submitInfo =
668 vk::VK_STRUCTURE_TYPE_SUBMIT_INFO, // VkStructureType sType;
669 DE_NULL, // const void* pNext;
670 0, // deUint32 waitSemaphoreCount;
671 DE_NULL, // const VkSemaphore* pWaitSemaphores;
672 1, // deUint32 commandBufferCount;
673 &m_copyResultsCommandBuffer.get(), // const VkCommandBuffer* pCommandBuffers;
674 0, // deUint32 signalSemaphoreCount;
675 DE_NULL // const VkSemaphore* pSignalSemaphores;
677 vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
681 if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
683 // In case of vkCmdCopyQueryResults is used, test must always wait for it
684 // to complete before we can read the result buffer.
686 VK_CHECK(vk.queueWaitIdle(queue));
689 deUint64 queryResults [NUM_QUERIES_IN_POOL];
690 deUint64 queryAvailability [NUM_QUERIES_IN_POOL];
692 // Allow not ready results only if nobody waited before getting the query results
693 bool allowNotReady = (m_testVector.queryWait == WAIT_NONE);
695 captureResults(queryResults, queryAvailability, allowNotReady);
697 log << tcu::TestLog::Section("OcclusionQueryResults", "Occlusion query results");
699 logResults(queryResults, queryAvailability);
700 bool passed = validateResults(queryResults, queryAvailability, allowNotReady, m_testVector.primitiveRopology);
702 log << tcu::TestLog::EndSection;
708 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed");
710 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed");
713 vk::Move<vk::VkCommandBuffer> OcclusionQueryTestInstance::recordRender (vk::VkCommandPool cmdPool)
715 const vk::VkDevice device = m_context.getDevice();
716 const vk::VkQueue queue = m_context.getUniversalQueue();
717 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
719 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
721 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
722 DE_NULL, // const void* pNext;
723 cmdPool, // VkCommandPool commandPool;
724 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
725 1u, // deUint32 bufferCount;
727 vk::Move<vk::VkCommandBuffer> cmdBuffer (vk::allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo));
728 CmdBufferBeginInfo beginInfo (DE_NULL, 0, DE_NULL, 0u, true, m_testVector.queryControlFlags);
730 vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
732 transition2DImage(vk, *cmdBuffer, m_stateObjects->m_ColorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
733 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);
735 std::vector<vk::VkClearValue> renderPassClearValues(2);
736 deMemset(&renderPassClearValues[0], static_cast<int>(renderPassClearValues.size()) * sizeof(vk::VkClearValue), 0);
738 const vk::VkRect2D renderArea =
741 { StateObjects::WIDTH, StateObjects::HEIGHT }
744 RenderPassBeginInfo renderPassBegin(*m_stateObjects->m_RenderPass, *m_stateObjects->m_Framebuffer, renderArea, renderPassClearValues);
746 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBegin, vk::VK_SUBPASS_CONTENTS_INLINE);
748 vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stateObjects->m_Pipeline);
750 vk::VkBuffer vertexBuffer = m_stateObjects->m_VertexBuffer->object();
751 const vk::VkDeviceSize vertexBufferOffset = 0;
752 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
754 vk.cmdResetQueryPool(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL);
756 // Draw un-occluded geometry
757 vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_ALL, m_testVector.queryControlFlags);
758 vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, START_VERTEX, 0);
759 vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_ALL);
761 // Partially occlude geometry
762 vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL, 1, START_VERTEX_PARTIALLY_OCCLUDED, 0);
764 // Draw partially-occluded geometry
765 vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED, m_testVector.queryControlFlags);
766 vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, START_VERTEX, 0);
767 vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED);
770 vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_OCCLUDER_DRAWCALL, 1, START_VERTEX_OCCLUDER, 0);
772 // Draw occluded geometry
773 vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_OCCLUDED, m_testVector.queryControlFlags);
774 vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_DRAWCALL, 1, START_VERTEX, 0);
775 vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_OCCLUDED);
777 if (m_testVector.queryWait != WAIT_QUEUE )
779 //For WAIT_QUEUE another cmdBuffer is issued with cmdCopyQueryPoolResults
780 if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
782 vk.cmdCopyQueryPoolResults(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL, m_queryPoolResultsBuffer->object(), /*dstOffset*/ 0, m_testVector.queryResultsStride, m_queryResultFlags);
786 vk.cmdEndRenderPass(*cmdBuffer);
788 transition2DImage(vk, *cmdBuffer, m_stateObjects->m_ColorAttachmentImage->object(), vk::VK_IMAGE_ASPECT_COLOR_BIT, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
790 vk.endCommandBuffer(*cmdBuffer);
795 vk::Move<vk::VkCommandBuffer> OcclusionQueryTestInstance::recordCopyResults (vk::VkCommandPool cmdPool)
797 const vk::VkDevice device = m_context.getDevice();
798 const vk::VkQueue queue = m_context.getUniversalQueue();
799 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
801 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
803 vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType sType;
804 DE_NULL, // const void* pNext;
805 cmdPool, // VkCommandPool commandPool;
806 vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY, // VkCommandBufferLevel level;
807 1u, // deUint32 bufferCount;
809 vk::Move<vk::VkCommandBuffer> cmdBuffer (vk::allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo));
810 const CmdBufferBeginInfo beginInfo (DE_NULL, 0, DE_NULL, 0u, true, m_testVector.queryControlFlags);
812 vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
813 vk.cmdCopyQueryPoolResults(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL, m_queryPoolResultsBuffer->object(), /*dstOffset*/ 0, m_testVector.queryResultsStride, m_queryResultFlags);
814 vk.endCommandBuffer(*cmdBuffer);
819 void OcclusionQueryTestInstance::captureResults (deUint64* retResults, deUint64* retAvailAbility, bool allowNotReady)
822 const vk::VkDevice device = m_context.getDevice();
823 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
824 std::vector<deUint8> resultsBuffer (m_testVector.queryResultsStride * NUM_QUERIES_IN_POOL);
826 if (m_testVector.queryResultsMode == RESULTS_MODE_GET)
828 const vk::VkResult queryResult = vk.getQueryPoolResults(device, m_queryPool, 0, NUM_QUERIES_IN_POOL, resultsBuffer.size(), &resultsBuffer[0], m_testVector.queryResultsStride, m_queryResultFlags);
829 if (queryResult == vk::VK_NOT_READY && !allowNotReady)
831 TCU_FAIL("getQueryPoolResults returned VK_NOT_READY, but results should be already available.");
835 VK_CHECK(queryResult);
838 else if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
840 const vk::Allocation& allocation = m_queryPoolResultsBuffer->getBoundMemory();
841 const void* allocationData = allocation.getHostPtr();
843 vk::invalidateMappedMemoryRange(vk, device, allocation.getMemory(), allocation.getOffset(), resultsBuffer.size());
845 deMemcpy(&resultsBuffer[0], allocationData, resultsBuffer.size());
848 for (int queryNdx = 0; queryNdx < NUM_QUERIES_IN_POOL; queryNdx++)
850 const void* srcPtr = &resultsBuffer[queryNdx * m_testVector.queryResultsStride];
851 if (m_testVector.queryResultSize == RESULT_SIZE_32_BIT)
853 const deUint32* srcPtrTyped = static_cast<const deUint32*>(srcPtr);
854 retResults[queryNdx] = *srcPtrTyped;
855 if (m_testVector.queryResultsAvailability)
857 retAvailAbility[queryNdx] = *(srcPtrTyped + 1);
860 else if (m_testVector.queryResultSize == RESULT_SIZE_64_BIT)
862 const deUint64* srcPtrTyped = static_cast<const deUint64*>(srcPtr);
863 retResults[queryNdx] = *srcPtrTyped;
865 if (m_testVector.queryResultsAvailability)
867 if (m_testVector.queryResultsAvailability)
869 retAvailAbility[queryNdx] = *(srcPtrTyped + 1);
875 TCU_FAIL("Wrong m_testVector.queryResultSize");
880 void OcclusionQueryTestInstance::logResults (const deUint64* results, const deUint64* availability)
882 tcu::TestLog& log = m_context.getTestContext().getLog();
884 for (int ndx = 0; ndx < NUM_QUERIES_IN_POOL; ++ndx)
886 if (!m_testVector.queryResultsAvailability)
888 log << tcu::TestLog::Message << "query[ slot == " << ndx << "] result == " << results[ndx] << tcu::TestLog::EndMessage;
892 log << tcu::TestLog::Message << "query[ slot == " << ndx << "] result == " << results[ndx] << ", availability == " << availability[ndx] << tcu::TestLog::EndMessage;
897 bool OcclusionQueryTestInstance::validateResults (const deUint64* results , const deUint64* availability, bool allowUnavailable, vk::VkPrimitiveTopology primitiveTopology)
900 tcu::TestLog& log = m_context.getTestContext().getLog();
902 for (int queryNdx = 0; queryNdx < NUM_QUERIES_IN_POOL; ++queryNdx)
904 deUint64 expectedValueMin = 0;
905 deUint64 expectedValueMax = 0;
907 if (m_testVector.queryResultsAvailability && availability[queryNdx] == 0)
909 // query result was not available
910 if (!allowUnavailable)
912 log << tcu::TestLog::Message << "query results availability was 0 for index "
913 << queryNdx << ", expected any value greater than 0." << tcu::TestLog::EndMessage;
920 // query is available, so expect proper result values
921 if (primitiveTopology == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
925 case QUERY_INDEX_CAPTURE_OCCLUDED:
926 expectedValueMin = 0;
927 expectedValueMax = 0;
929 case QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED:
930 expectedValueMin = 1;
931 expectedValueMax = 1;
933 case QUERY_INDEX_CAPTURE_ALL:
934 expectedValueMin = NUM_VERTICES_IN_DRAWCALL;
935 expectedValueMax = NUM_VERTICES_IN_DRAWCALL;
939 else if (primitiveTopology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
943 case QUERY_INDEX_CAPTURE_OCCLUDED:
944 expectedValueMin = 0;
945 expectedValueMax = 0;
947 case QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED:
948 case QUERY_INDEX_CAPTURE_ALL:
950 const int primWidth = StateObjects::WIDTH / 2;
951 const int primHeight = StateObjects::HEIGHT / 2;
952 const int primArea = primWidth * primHeight / 2;
953 expectedValueMin = (int)(0.97f * primArea);
954 expectedValueMax = (int)(1.03f * primArea);
960 TCU_FAIL("Unsupported primitive topology");
964 if ((m_testVector.queryControlFlags & vk::VK_QUERY_CONTROL_PRECISE_BIT) || (expectedValueMin == 0 && expectedValueMax == 0))
966 // require precise value
967 if (results[queryNdx] < expectedValueMin || results[queryNdx] > expectedValueMax)
969 log << tcu::TestLog::Message << "wrong value of query for index "
970 << queryNdx << ", expected the value minimum of " << expectedValueMin << ", maximum of " << expectedValueMax << " got "
971 << results[queryNdx] << "." << tcu::TestLog::EndMessage;
977 // require imprecise value greater than 0
978 if (results[queryNdx] == 0)
980 log << tcu::TestLog::Message << "wrong value of query for index "
981 << queryNdx << ", expected any non-zero value, got "
982 << results[queryNdx] << "." << tcu::TestLog::EndMessage;
990 void OcclusionQueryTestInstance::logRenderTarget (void)
992 tcu::TestLog& log = m_context.getTestContext().getLog();
993 const vk::VkQueue queue = m_context.getUniversalQueue();
994 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
995 tcu::ConstPixelBufferAccess resultImageAccess = m_stateObjects->m_ColorAttachmentImage->readSurface(
996 queue, m_context.getDefaultAllocator(), vk::VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
997 zeroOffset, StateObjects::HEIGHT, StateObjects::WIDTH, vk::VK_IMAGE_ASPECT_COLOR_BIT);
999 log << tcu::TestLog::Image("Result", "Result", resultImageAccess);
1002 template<class Instance>
1003 class QueryPoolOcclusionTest : public vkt::TestCase
1006 QueryPoolOcclusionTest (tcu::TestContext &context, const char *name, const char *description, const OcclusionQueryTestVector& testVector)
1007 : TestCase (context, name, description)
1008 , m_testVector (testVector)
1012 vkt::TestInstance* createInstance (vkt::Context& context) const
1014 return new Instance(context, m_testVector);
1017 void initPrograms(vk::SourceCollections& programCollection) const
1019 programCollection.glslSources.add("frag") << glu::FragmentSource("#version 400\n"
1020 "layout(location = 0) out vec4 out_FragColor;\n"
1023 " out_FragColor = vec4(0.07, 0.48, 0.75, 1.0);\n"
1026 programCollection.glslSources.add("vert") << glu::VertexSource("#version 430\n"
1027 "layout(location = 0) in vec4 in_Postion;\n"
1029 " gl_Position = in_Postion;\n"
1030 " gl_PointSize = 1.0;\n"
1034 OcclusionQueryTestVector m_testVector;
1045 QueryPoolOcclusionTests::QueryPoolOcclusionTests (tcu::TestContext &testCtx)
1046 : TestCaseGroup(testCtx, "occlusion_query", "Tests for occlusion queries")
1048 /* Left blank on purpose */
1051 QueryPoolOcclusionTests::~QueryPoolOcclusionTests (void)
1053 /* Left blank on purpose */
1056 void QueryPoolOcclusionTests::init (void)
1058 OcclusionQueryTestVector baseTestVector;
1059 baseTestVector.queryControlFlags = 0;
1060 baseTestVector.queryResultSize = RESULT_SIZE_64_BIT;
1061 baseTestVector.queryWait = WAIT_QUEUE;
1062 baseTestVector.queryResultsMode = RESULTS_MODE_GET;
1063 baseTestVector.queryResultsStride = sizeof(deUint64);
1064 baseTestVector.queryResultsAvailability = false;
1065 baseTestVector.primitiveRopology = vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
1069 OcclusionQueryTestVector testVector = baseTestVector;
1070 testVector.queryControlFlags = 0;
1071 addChild(new QueryPoolOcclusionTest<BasicOcclusionQueryTestInstance>(m_testCtx, "basic_conservative", "draw with conservative occlusion query", testVector));
1072 testVector.queryControlFlags = vk::VK_QUERY_CONTROL_PRECISE_BIT;
1073 addChild(new QueryPoolOcclusionTest<BasicOcclusionQueryTestInstance>(m_testCtx, "basic_precise", "draw with precise occlusion query", testVector));
1078 vk::VkQueryControlFlags controlFlags[] = { 0, vk::VK_QUERY_CONTROL_PRECISE_BIT };
1079 const char* controlFlagsStr[] = { "conservative", "precise" };
1081 for (int controlFlagIdx = 0; controlFlagIdx < DE_LENGTH_OF_ARRAY(controlFlags); ++controlFlagIdx)
1084 vk::VkPrimitiveTopology primitiveTopology[] = { vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST };
1085 const char* primitiveTopologyStr[] = { "points", "triangles" };
1086 for (int primitiveTopologyIdx = 0; primitiveTopologyIdx < DE_LENGTH_OF_ARRAY(primitiveTopology); ++primitiveTopologyIdx)
1089 OcclusionQueryResultSize resultSize[] = { RESULT_SIZE_32_BIT, RESULT_SIZE_64_BIT };
1090 const char* resultSizeStr[] = { "32", "64" };
1092 for (int resultSizeIdx = 0; resultSizeIdx < DE_LENGTH_OF_ARRAY(resultSize); ++resultSizeIdx)
1095 OcclusionQueryWait wait[] = { WAIT_QUEUE, WAIT_QUERY };
1096 const char* waitStr[] = { "queue", "query" };
1098 for (int waitIdx = 0; waitIdx < DE_LENGTH_OF_ARRAY(wait); ++waitIdx)
1100 OcclusionQueryResultsMode resultsMode[] = { RESULTS_MODE_GET, RESULTS_MODE_COPY };
1101 const char* resultsModeStr[] = { "get", "copy" };
1103 for (int resultsModeIdx = 0; resultsModeIdx < DE_LENGTH_OF_ARRAY(resultsMode); ++resultsModeIdx)
1106 bool testAvailability[] = { false, true };
1107 const char* testAvailabilityStr[] = { "without", "with"};
1109 for (int testAvailabilityIdx = 0; testAvailabilityIdx < DE_LENGTH_OF_ARRAY(testAvailability); ++testAvailabilityIdx)
1111 OcclusionQueryTestVector testVector = baseTestVector;
1112 testVector.queryControlFlags = controlFlags[controlFlagIdx];
1113 testVector.queryResultSize = resultSize[resultSizeIdx];
1114 testVector.queryWait = wait[waitIdx];
1115 testVector.queryResultsMode = resultsMode[resultsModeIdx];
1116 testVector.queryResultsStride = (testVector.queryResultSize == RESULT_SIZE_32_BIT ? sizeof(deUint32) : sizeof(deUint64));
1117 testVector.queryResultsAvailability = testAvailability[testAvailabilityIdx];
1118 testVector.primitiveRopology = primitiveTopology[primitiveTopologyIdx];
1120 if (testVector.queryResultsAvailability)
1122 testVector.queryResultsStride *= 2;
1125 std::ostringstream testName;
1126 std::ostringstream testDescr;
1128 testName << resultsModeStr[resultsModeIdx] << "_results"
1129 << "_" << controlFlagsStr[controlFlagIdx]
1130 << "_size_" << resultSizeStr[resultSizeIdx]
1131 << "_wait_" << waitStr[waitIdx]
1132 << "_" << testAvailabilityStr[testAvailabilityIdx] << "_availability"
1133 << "_draw_" << primitiveTopologyStr[primitiveTopologyIdx];
1135 testDescr << "draw occluded " << primitiveTopologyStr[primitiveTopologyIdx]
1136 << "with " << controlFlagsStr[controlFlagIdx] << ", "
1137 << resultsModeStr[resultsModeIdx] << " results "
1138 << testAvailabilityStr[testAvailabilityIdx] << " availability bit as "
1139 << resultSizeStr[resultSizeIdx] << "bit variables,"
1140 << "wait for results on" << waitStr[waitIdx];
1142 addChild(new QueryPoolOcclusionTest<OcclusionQueryTestInstance>(m_testCtx, testName.str().c_str(), testDescr.str().c_str(), testVector));
1150 // Test different strides
1152 OcclusionQueryResultsMode resultsMode[] = { RESULTS_MODE_GET, RESULTS_MODE_COPY };
1153 const char* resultsModeStr[] = { "get", "copy" };
1155 for (int resultsModeIdx = 0; resultsModeIdx < DE_LENGTH_OF_ARRAY(resultsMode); ++resultsModeIdx)
1157 OcclusionQueryResultSize resultSizes[] = { RESULT_SIZE_32_BIT, RESULT_SIZE_64_BIT };
1158 const char* resultSizeStr[] = { "32", "64" };
1160 bool testAvailability[] = { false, true };
1161 const char* testAvailabilityStr[] = { "without", "with" };
1163 for (int testAvailabilityIdx = 0; testAvailabilityIdx < DE_LENGTH_OF_ARRAY(testAvailability); ++testAvailabilityIdx)
1165 for (int resultSizeIdx = 0; resultSizeIdx < DE_LENGTH_OF_ARRAY(resultSizes); ++resultSizeIdx)
1167 const vk::VkDeviceSize resultSize = (resultSizes[resultSizeIdx] == RESULT_SIZE_32_BIT ? sizeof(deUint32) : sizeof(deUint64));
1169 // \todo [2015-12-18 scygan] Ensure only stride values aligned to resultSize are allowed. Otherwise test should be extended.
1170 const vk::VkDeviceSize strides[] =
1181 for (int strideIdx = 0; strideIdx < DE_LENGTH_OF_ARRAY(strides); strideIdx++)
1183 OcclusionQueryTestVector testVector = baseTestVector;
1184 testVector.queryResultsMode = resultsMode[resultsModeIdx];
1185 testVector.queryResultSize = resultSizes[resultSizeIdx];
1186 testVector.queryResultsAvailability = testAvailability[testAvailabilityIdx];
1187 testVector.queryResultsStride = strides[strideIdx];
1189 const vk::VkDeviceSize elementSize = (testVector.queryResultsAvailability ? resultSize * 2 : resultSize);
1191 if (elementSize > testVector.queryResultsStride)
1196 std::ostringstream testName;
1197 std::ostringstream testDescr;
1199 testName << resultsModeStr[resultsModeIdx]
1200 << "_results_size_" << resultSizeStr[resultSizeIdx]
1201 << "_stride_" << strides[strideIdx]
1202 << "_" << testAvailabilityStr[testAvailabilityIdx] << "_availability";
1204 testDescr << resultsModeStr[resultsModeIdx] << " results "
1205 << testAvailabilityStr[testAvailabilityIdx] << " availability bit as "
1206 << resultSizeStr[resultSizeIdx] << "bit variables, with stride" << strides[strideIdx];
1208 addChild(new QueryPoolOcclusionTest<OcclusionQueryTestInstance>(m_testCtx, testName.str().c_str(), testDescr.str().c_str(), testVector));