1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Intel Corporation
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * \brief Vulkan Occlusion Query Tests
23 *//*--------------------------------------------------------------------*/
25 #include "vktQueryPoolOcclusionTests.hpp"
27 #include "vktTestCase.hpp"
29 #include "vktQueryPoolImageObjectUtil.hpp"
30 #include "vktQueryPoolBufferObjectUtil.hpp"
31 #include "vktQueryPoolCreateInfoUtil.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkPrograms.hpp"
36 #include "tcuTestLog.hpp"
37 #include "tcuResource.hpp"
38 #include "tcuImageCompare.hpp"
39 #include "tcuCommandLine.hpp"
41 using namespace vkt::QueryPool;
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);
57 vkt::Context &m_context;
59 vk::Move<vk::VkPipeline> m_pipeline;
60 vk::Move<vk::VkPipelineLayout> m_pipelineLayout;
62 de::SharedPtr<Image> m_colorAttachmentImage, m_DepthImage;
63 vk::Move<vk::VkImageView> m_attachmentView;
64 vk::Move<vk::VkImageView> m_depthiew;
66 vk::Move<vk::VkRenderPass> m_renderPass;
67 vk::Move<vk::VkFramebuffer> m_framebuffer;
69 de::SharedPtr<Buffer> m_vertexBuffer;
71 vk::VkFormat m_colorAttachmentFormat;
74 StateObjects::StateObjects (const vk::DeviceInterface&vk, vkt::Context &context, const int numVertices, vk::VkPrimitiveTopology primitive)
76 , m_colorAttachmentFormat(vk::VK_FORMAT_R8G8B8A8_UNORM)
79 vk::VkFormat depthFormat = vk::VK_FORMAT_D16_UNORM;
80 const vk::VkDevice device = m_context.getDevice();
82 //attachment images and views
84 vk::VkExtent3D imageExtent =
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);
94 m_colorAttachmentImage = Image::createAndAlloc(vk, device, colorImageCreateInfo, m_context.getDefaultAllocator());
96 const ImageViewCreateInfo attachmentViewInfo(m_colorAttachmentImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, m_colorAttachmentFormat);
97 m_attachmentView = vk::createImageView(vk, device, &attachmentViewInfo);
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);
102 m_DepthImage = Image::createAndAlloc(vk, device, depthImageCreateInfo, m_context.getDefaultAllocator());
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);
110 // Renderpass and Framebuffer
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
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
131 const vk::VkAttachmentReference colorAttachmentReference =
134 vk::VK_IMAGE_LAYOUT_GENERAL // layout
137 const vk::VkAttachmentReference depthAttachmentReference =
140 vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // layout
143 renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS, // pipelineBindPoint
146 DE_NULL, // pInputAttachments
148 &colorAttachmentReference, // pColorAttachments
149 DE_NULL, // pResolveAttachments
150 depthAttachmentReference, // depthStencilAttachment
152 DE_NULL)); // preserveAttachments
154 m_renderPass = vk::createRenderPass(vk, device, &renderPassCreateInfo);
156 std::vector<vk::VkImageView> attachments(2);
157 attachments[0] = *m_attachmentView;
158 attachments[1] = *m_depthiew;
160 FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, attachments, WIDTH, HEIGHT, 1);
161 m_framebuffer = vk::createFramebuffer(vk, device, &framebufferCreateInfo);
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));
170 const PipelineCreateInfo::ColorBlendState::Attachment attachmentState;
172 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
173 m_pipelineLayout = vk::createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
175 const vk::VkVertexInputBindingDescription vf_binding_desc =
178 4 * (deUint32)sizeof(float), // stride;
179 vk::VK_VERTEX_INPUT_RATE_VERTEX // inputRate
182 const vk::VkVertexInputAttributeDescription vf_attribute_desc =
186 vk::VK_FORMAT_R32G32B32A32_SFLOAT, // format;
190 const vk::VkPipelineVertexInputStateCreateInfo vf_info =
192 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // pNext;
194 0u, // vertexBindingDescriptionCount;
195 1, // pVertexBindingDescriptions;
196 &vf_binding_desc, // vertexAttributeDescriptionCount;
197 1, // pVertexAttributeDescriptions;
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 =
210 WIDTH, // float width;
211 HEIGHT, // float height;
212 0.0f, // float minDepth;
213 1.0f // float maxDepth;
216 const vk::VkRect2D scissor =
221 }, // VkOffset2D offset;
223 WIDTH, // deInt32 width;
224 HEIGHT, // deInt32 height
225 }, // VkExtent2D extent;
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);
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);
242 void StateObjects::setVertices (const vk::DeviceInterface&vk, std::vector<tcu::Vec4> vertices)
244 const vk::VkDevice device = m_context.getDevice();
246 tcu::Vec4 *ptr = reinterpret_cast<tcu::Vec4*>(m_vertexBuffer->getBoundMemory().getHostPtr());
247 std::copy(vertices.begin(), vertices.end(), ptr);
249 vk::flushMappedMemoryRange(vk, device, m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(), vertices.size() * sizeof(vertices[0]));
252 enum OcclusionQueryResultSize
258 enum OcclusionQueryWait
265 enum OcclusionQueryResultsMode
271 struct OcclusionQueryTestVector
273 vk::VkQueryControlFlags queryControlFlags;
274 OcclusionQueryResultSize queryResultSize;
275 OcclusionQueryWait queryWait;
276 OcclusionQueryResultsMode queryResultsMode;
277 vk::VkDeviceSize queryResultsStride;
278 bool queryResultsAvailability;
279 vk::VkPrimitiveTopology primitiveTopology;
282 class BasicOcclusionQueryTestInstance : public vkt::TestInstance
285 BasicOcclusionQueryTestInstance (vkt::Context &context, const OcclusionQueryTestVector& testVector);
286 ~BasicOcclusionQueryTestInstance (void);
288 tcu::TestStatus iterate (void);
292 NUM_QUERIES_IN_POOL = 2,
293 QUERY_INDEX_CAPTURE_EMPTY = 0,
294 QUERY_INDEX_CAPTURE_DRAWCALL = 1,
295 NUM_VERTICES_IN_DRAWCALL = 3
298 OcclusionQueryTestVector m_testVector;
299 StateObjects* m_stateObjects;
300 vk::VkQueryPool m_queryPool;
303 BasicOcclusionQueryTestInstance::BasicOcclusionQueryTestInstance (vkt::Context &context, const OcclusionQueryTestVector& testVector)
304 : TestInstance (context)
305 , m_testVector (testVector)
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);
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");
317 m_stateObjects = new StateObjects(m_context.getDeviceInterface(), m_context, NUM_VERTICES_IN_DRAWCALL, m_testVector.primitiveTopology);
319 const vk::VkDevice device = m_context.getDevice();
320 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
322 const vk::VkQueryPoolCreateInfo queryPoolCreateInfo =
324 vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
327 vk::VK_QUERY_TYPE_OCCLUSION,
331 VK_CHECK(vk.createQueryPool(device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL, &m_queryPool));
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);
340 BasicOcclusionQueryTestInstance::~BasicOcclusionQueryTestInstance (void)
343 delete m_stateObjects;
345 if (m_queryPool != DE_NULL)
347 const vk::VkDevice device = m_context.getDevice();
348 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
350 vk.destroyQueryPool(device, m_queryPool, /*pAllocator*/ DE_NULL);
354 tcu::TestStatus BasicOcclusionQueryTestInstance::iterate (void)
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();
361 const CmdPoolCreateInfo cmdPoolCreateInfo (m_context.getUniversalQueueFamilyIndex());
362 vk::Move<vk::VkCommandPool> cmdPool = vk::createCommandPool(vk, device, &cmdPoolCreateInfo);
364 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
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;
372 vk::Unique<vk::VkCommandBuffer> cmdBuffer (vk::allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo));
373 const CmdBufferBeginInfo beginInfo (0u);
375 vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
377 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);
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);
380 std::vector<vk::VkClearValue> renderPassClearValues(2);
381 deMemset(&renderPassClearValues[0], 0, static_cast<int>(renderPassClearValues.size()) * sizeof(vk::VkClearValue));
383 const vk::VkRect2D renderArea =
386 { StateObjects::WIDTH, StateObjects::HEIGHT }
389 RenderPassBeginInfo renderPassBegin(*m_stateObjects->m_renderPass, *m_stateObjects->m_framebuffer, renderArea, renderPassClearValues);
391 vk.cmdResetQueryPool(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL);
393 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBegin, vk::VK_SUBPASS_CONTENTS_INLINE);
395 vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stateObjects->m_pipeline);
397 vk::VkBuffer vertexBuffer = m_stateObjects->m_vertexBuffer->object();
398 const vk::VkDeviceSize vertexBufferOffset = 0;
399 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
401 vk.cmdBeginQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_EMPTY, m_testVector.queryControlFlags);
402 vk.cmdEndQuery(*cmdBuffer, m_queryPool, QUERY_INDEX_CAPTURE_EMPTY);
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);
408 vk.cmdEndRenderPass(*cmdBuffer);
410 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);
412 vk.endCommandBuffer(*cmdBuffer);
414 // Submit command buffer
415 const vk::VkSubmitInfo submitInfo =
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;
427 vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
429 VK_CHECK(vk.queueWaitIdle(queue));
431 deUint64 queryResults[NUM_QUERIES_IN_POOL] = { 0 };
432 size_t queryResultsSize = sizeof(queryResults);
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);
436 if (queryResult == vk::VK_NOT_READY)
438 TCU_FAIL("Query result not avaliable, but vkWaitIdle() was called.");
441 VK_CHECK(queryResult);
443 log << tcu::TestLog::Section("OcclusionQueryResults",
444 "Occlusion query results");
445 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(queryResults); ++ndx)
447 log << tcu::TestLog::Message << "query[ slot == " << ndx
448 << "] result == " << queryResults[ndx] << tcu::TestLog::EndMessage;
453 for (int queryNdx = 0; queryNdx < DE_LENGTH_OF_ARRAY(queryResults); ++queryNdx)
456 deUint64 expectedValue;
460 case QUERY_INDEX_CAPTURE_EMPTY:
463 case QUERY_INDEX_CAPTURE_DRAWCALL:
464 expectedValue = NUM_VERTICES_IN_DRAWCALL;
468 if ((m_testVector.queryControlFlags & vk::VK_QUERY_CONTROL_PRECISE_BIT) || expectedValue == 0)
470 // require precise value
471 if (queryResults[queryNdx] != expectedValue)
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;
482 // require imprecize value > 0
483 if (queryResults[queryNdx] == 0)
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;
493 log << tcu::TestLog::EndSection;
497 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed");
499 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed");
502 class OcclusionQueryTestInstance : public vkt::TestInstance
505 OcclusionQueryTestInstance (vkt::Context &context, const OcclusionQueryTestVector& testVector);
506 ~OcclusionQueryTestInstance (void);
508 tcu::TestStatus iterate (void);
510 vk::Move<vk::VkCommandBuffer> recordRender (vk::VkCommandPool commandPool);
511 vk::Move<vk::VkCommandBuffer> recordCopyResults (vk::VkCommandPool commandPool);
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);
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
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
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
538 OcclusionQueryTestVector m_testVector;
540 const vk::VkQueryResultFlags m_queryResultFlags;
542 StateObjects* m_stateObjects;
543 vk::VkQueryPool m_queryPool;
544 de::SharedPtr<Buffer> m_queryPoolResultsBuffer;
546 vk::Move<vk::VkCommandPool> m_commandPool;
547 vk::Move<vk::VkCommandBuffer> m_renderCommandBuffer;
548 vk::Move<vk::VkCommandBuffer> m_copyResultsCommandBuffer;
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))
558 const vk::VkDevice device = m_context.getDevice();
559 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
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");
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);
566 const vk::VkQueryPoolCreateInfo queryPoolCreateInfo =
568 vk::VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,
571 vk::VK_QUERY_TYPE_OCCLUSION,
576 VK_CHECK(vk.createQueryPool(device, &queryPoolCreateInfo, /*pAllocator*/ DE_NULL, &m_queryPool));
578 if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
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);
584 const CmdPoolCreateInfo cmdPoolCreateInfo (m_context.getUniversalQueueFamilyIndex());
585 m_commandPool = vk::createCommandPool(vk, device, &cmdPoolCreateInfo);
586 m_renderCommandBuffer = recordRender(*m_commandPool);
588 if (m_testVector.queryWait == WAIT_QUEUE && m_testVector.queryResultsMode == RESULTS_MODE_COPY)
590 m_copyResultsCommandBuffer = recordCopyResults(*m_commandPool);
594 OcclusionQueryTestInstance::~OcclusionQueryTestInstance (void)
596 const vk::VkDevice device = m_context.getDevice();
599 delete m_stateObjects;
601 if (m_queryPool != DE_NULL)
603 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
604 vk.destroyQueryPool(device, m_queryPool, /*pAllocator*/ DE_NULL);
608 tcu::TestStatus OcclusionQueryTestInstance::iterate (void)
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);
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);
628 m_stateObjects->setVertices(vk, vertices);
631 const vk::VkSubmitInfo submitInfo =
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;
643 vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
646 if (m_testVector.queryWait == WAIT_QUEUE)
648 VK_CHECK(vk.queueWaitIdle(queue));
650 if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
652 // In case of WAIT_QUEUE test variant, the previously submitted m_renderCommandBuffer did not
653 // contain vkCmdCopyQueryResults, so additional cmd buffer is needed.
655 // In the case of WAIT_NONE or WAIT_QUERY, vkCmdCopyQueryResults is stored in m_renderCommandBuffer.
657 const vk::VkSubmitInfo submitInfo =
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;
669 vk.queueSubmit(queue, 1, &submitInfo, DE_NULL);
673 if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
675 // In case of vkCmdCopyQueryResults is used, test must always wait for it
676 // to complete before we can read the result buffer.
678 VK_CHECK(vk.queueWaitIdle(queue));
681 deUint64 queryResults [NUM_QUERIES_IN_POOL];
682 deUint64 queryAvailability [NUM_QUERIES_IN_POOL];
684 // Allow not ready results only if nobody waited before getting the query results
685 bool allowNotReady = (m_testVector.queryWait == WAIT_NONE);
687 captureResults(queryResults, queryAvailability, allowNotReady);
689 log << tcu::TestLog::Section("OcclusionQueryResults", "Occlusion query results");
691 logResults(queryResults, queryAvailability);
692 bool passed = validateResults(queryResults, queryAvailability, allowNotReady, m_testVector.primitiveTopology);
694 log << tcu::TestLog::EndSection;
696 if (m_testVector.queryResultsMode != RESULTS_MODE_COPY)
698 VK_CHECK(vk.queueWaitIdle(queue));
703 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Query result verification passed");
705 return tcu::TestStatus(QP_TEST_RESULT_FAIL, "Query result verification failed");
708 vk::Move<vk::VkCommandBuffer> OcclusionQueryTestInstance::recordRender (vk::VkCommandPool cmdPool)
710 const vk::VkDevice device = m_context.getDevice();
711 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
713 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
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;
721 vk::Move<vk::VkCommandBuffer> cmdBuffer (vk::allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo));
722 CmdBufferBeginInfo beginInfo (0u);
724 vk.beginCommandBuffer(*cmdBuffer, &beginInfo);
726 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);
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);
729 std::vector<vk::VkClearValue> renderPassClearValues(2);
730 deMemset(&renderPassClearValues[0], 0, static_cast<int>(renderPassClearValues.size()) * sizeof(vk::VkClearValue));
732 const vk::VkRect2D renderArea =
735 { StateObjects::WIDTH, StateObjects::HEIGHT }
738 RenderPassBeginInfo renderPassBegin(*m_stateObjects->m_renderPass, *m_stateObjects->m_framebuffer, renderArea, renderPassClearValues);
740 vk.cmdResetQueryPool(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL);
742 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBegin, vk::VK_SUBPASS_CONTENTS_INLINE);
744 vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *m_stateObjects->m_pipeline);
746 vk::VkBuffer vertexBuffer = m_stateObjects->m_vertexBuffer->object();
747 const vk::VkDeviceSize vertexBufferOffset = 0;
748 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
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);
755 // Partially occlude geometry
756 vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_PARTIALLY_OCCLUDED_DRAWCALL, 1, START_VERTEX_PARTIALLY_OCCLUDED, 0);
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);
764 vk.cmdDraw(*cmdBuffer, NUM_VERTICES_IN_OCCLUDER_DRAWCALL, 1, START_VERTEX_OCCLUDER, 0);
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);
771 vk.cmdEndRenderPass(*cmdBuffer);
773 if (m_testVector.queryWait != WAIT_QUEUE )
775 //For WAIT_QUEUE another cmdBuffer is issued with cmdCopyQueryPoolResults
776 if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
778 vk.cmdCopyQueryPoolResults(*cmdBuffer, m_queryPool, 0, NUM_QUERIES_IN_POOL, m_queryPoolResultsBuffer->object(), /*dstOffset*/ 0, m_testVector.queryResultsStride, m_queryResultFlags);
782 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);
784 vk.endCommandBuffer(*cmdBuffer);
789 vk::Move<vk::VkCommandBuffer> OcclusionQueryTestInstance::recordCopyResults (vk::VkCommandPool cmdPool)
791 const vk::VkDevice device = m_context.getDevice();
792 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
794 const vk::VkCommandBufferAllocateInfo cmdBufferAllocateInfo =
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;
802 vk::Move<vk::VkCommandBuffer> cmdBuffer (vk::allocateCommandBuffer(vk, device, &cmdBufferAllocateInfo));
803 const CmdBufferBeginInfo beginInfo (0u);
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);
812 void OcclusionQueryTestInstance::captureResults (deUint64* retResults, deUint64* retAvailAbility, bool allowNotReady)
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);
819 if (m_testVector.queryResultsMode == RESULTS_MODE_GET)
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)
824 TCU_FAIL("getQueryPoolResults returned VK_NOT_READY, but results should be already available.");
828 VK_CHECK(queryResult);
831 else if (m_testVector.queryResultsMode == RESULTS_MODE_COPY)
833 const vk::Allocation& allocation = m_queryPoolResultsBuffer->getBoundMemory();
834 const void* allocationData = allocation.getHostPtr();
836 vk::invalidateMappedMemoryRange(vk, device, allocation.getMemory(), allocation.getOffset(), resultsBuffer.size());
838 deMemcpy(&resultsBuffer[0], allocationData, resultsBuffer.size());
841 for (int queryNdx = 0; queryNdx < NUM_QUERIES_IN_POOL; queryNdx++)
843 const void* srcPtr = &resultsBuffer[queryNdx * static_cast<size_t>(m_testVector.queryResultsStride)];
844 if (m_testVector.queryResultSize == RESULT_SIZE_32_BIT)
846 const deUint32* srcPtrTyped = static_cast<const deUint32*>(srcPtr);
847 retResults[queryNdx] = *srcPtrTyped;
848 if (m_testVector.queryResultsAvailability)
850 retAvailAbility[queryNdx] = *(srcPtrTyped + 1);
853 else if (m_testVector.queryResultSize == RESULT_SIZE_64_BIT)
855 const deUint64* srcPtrTyped = static_cast<const deUint64*>(srcPtr);
856 retResults[queryNdx] = *srcPtrTyped;
858 if (m_testVector.queryResultsAvailability)
860 if (m_testVector.queryResultsAvailability)
862 retAvailAbility[queryNdx] = *(srcPtrTyped + 1);
868 TCU_FAIL("Wrong m_testVector.queryResultSize");
873 void OcclusionQueryTestInstance::logResults (const deUint64* results, const deUint64* availability)
875 tcu::TestLog& log = m_context.getTestContext().getLog();
877 for (int ndx = 0; ndx < NUM_QUERIES_IN_POOL; ++ndx)
879 if (!m_testVector.queryResultsAvailability)
881 log << tcu::TestLog::Message << "query[ slot == " << ndx << "] result == " << results[ndx] << tcu::TestLog::EndMessage;
885 log << tcu::TestLog::Message << "query[ slot == " << ndx << "] result == " << results[ndx] << ", availability == " << availability[ndx] << tcu::TestLog::EndMessage;
890 bool OcclusionQueryTestInstance::validateResults (const deUint64* results , const deUint64* availability, bool allowUnavailable, vk::VkPrimitiveTopology primitiveTopology)
893 tcu::TestLog& log = m_context.getTestContext().getLog();
895 for (int queryNdx = 0; queryNdx < NUM_QUERIES_IN_POOL; ++queryNdx)
897 deUint64 expectedValueMin = 0;
898 deUint64 expectedValueMax = 0;
900 if (m_testVector.queryResultsAvailability && availability[queryNdx] == 0)
902 // query result was not available
903 if (!allowUnavailable)
905 log << tcu::TestLog::Message << "query results availability was 0 for index "
906 << queryNdx << ", expected any value greater than 0." << tcu::TestLog::EndMessage;
913 // query is available, so expect proper result values
914 if (primitiveTopology == vk::VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
918 case QUERY_INDEX_CAPTURE_OCCLUDED:
919 expectedValueMin = 0;
920 expectedValueMax = 0;
922 case QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED:
923 expectedValueMin = 1;
924 expectedValueMax = 1;
926 case QUERY_INDEX_CAPTURE_ALL:
927 expectedValueMin = NUM_VERTICES_IN_DRAWCALL;
928 expectedValueMax = NUM_VERTICES_IN_DRAWCALL;
932 else if (primitiveTopology == vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
936 case QUERY_INDEX_CAPTURE_OCCLUDED:
937 expectedValueMin = 0;
938 expectedValueMax = 0;
940 case QUERY_INDEX_CAPTURE_PARTIALLY_OCCLUDED:
941 case QUERY_INDEX_CAPTURE_ALL:
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);
953 TCU_FAIL("Unsupported primitive topology");
957 if ((m_testVector.queryControlFlags & vk::VK_QUERY_CONTROL_PRECISE_BIT) || (expectedValueMin == 0 && expectedValueMax == 0))
959 // require precise value
960 if (results[queryNdx] < expectedValueMin || results[queryNdx] > expectedValueMax)
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;
970 // require imprecise value greater than 0
971 if (results[queryNdx] == 0)
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;
983 template<class Instance>
984 class QueryPoolOcclusionTest : public vkt::TestCase
987 QueryPoolOcclusionTest (tcu::TestContext &context, const char *name, const char *description, const OcclusionQueryTestVector& testVector)
988 : TestCase (context, name, description)
989 , m_testVector (testVector)
993 vkt::TestInstance* createInstance (vkt::Context& context) const
995 return new Instance(context, m_testVector);
998 void initPrograms(vk::SourceCollections& programCollection) const
1000 programCollection.glslSources.add("frag") << glu::FragmentSource("#version 400\n"
1001 "layout(location = 0) out vec4 out_FragColor;\n"
1004 " out_FragColor = vec4(0.07, 0.48, 0.75, 1.0);\n"
1007 programCollection.glslSources.add("vert") << glu::VertexSource("#version 430\n"
1008 "layout(location = 0) in vec4 in_Postion;\n"
1010 " gl_Position = in_Postion;\n"
1011 " gl_PointSize = 1.0;\n"
1015 OcclusionQueryTestVector m_testVector;
1026 QueryPoolOcclusionTests::QueryPoolOcclusionTests (tcu::TestContext &testCtx)
1027 : TestCaseGroup(testCtx, "occlusion_query", "Tests for occlusion queries")
1029 /* Left blank on purpose */
1032 QueryPoolOcclusionTests::~QueryPoolOcclusionTests (void)
1034 /* Left blank on purpose */
1037 void QueryPoolOcclusionTests::init (void)
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;
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));
1059 vk::VkQueryControlFlags controlFlags[] = { 0, vk::VK_QUERY_CONTROL_PRECISE_BIT };
1060 const char* controlFlagsStr[] = { "conservative", "precise" };
1062 for (int controlFlagIdx = 0; controlFlagIdx < DE_LENGTH_OF_ARRAY(controlFlags); ++controlFlagIdx)
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)
1070 OcclusionQueryResultSize resultSize[] = { RESULT_SIZE_32_BIT, RESULT_SIZE_64_BIT };
1071 const char* resultSizeStr[] = { "32", "64" };
1073 for (int resultSizeIdx = 0; resultSizeIdx < DE_LENGTH_OF_ARRAY(resultSize); ++resultSizeIdx)
1076 OcclusionQueryWait wait[] = { WAIT_QUEUE, WAIT_QUERY };
1077 const char* waitStr[] = { "queue", "query" };
1079 for (int waitIdx = 0; waitIdx < DE_LENGTH_OF_ARRAY(wait); ++waitIdx)
1081 OcclusionQueryResultsMode resultsMode[] = { RESULTS_MODE_GET, RESULTS_MODE_COPY };
1082 const char* resultsModeStr[] = { "get", "copy" };
1084 for (int resultsModeIdx = 0; resultsModeIdx < DE_LENGTH_OF_ARRAY(resultsMode); ++resultsModeIdx)
1087 bool testAvailability[] = { false, true };
1088 const char* testAvailabilityStr[] = { "without", "with"};
1090 for (int testAvailabilityIdx = 0; testAvailabilityIdx < DE_LENGTH_OF_ARRAY(testAvailability); ++testAvailabilityIdx)
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];
1101 if (testVector.queryResultsAvailability)
1103 testVector.queryResultsStride *= 2;
1106 std::ostringstream testName;
1107 std::ostringstream testDescr;
1109 testName << resultsModeStr[resultsModeIdx] << "_results"
1110 << "_" << controlFlagsStr[controlFlagIdx]
1111 << "_size_" << resultSizeStr[resultSizeIdx]
1112 << "_wait_" << waitStr[waitIdx]
1113 << "_" << testAvailabilityStr[testAvailabilityIdx] << "_availability"
1114 << "_draw_" << primitiveTopologyStr[primitiveTopologyIdx];
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];
1123 addChild(new QueryPoolOcclusionTest<OcclusionQueryTestInstance>(m_testCtx, testName.str().c_str(), testDescr.str().c_str(), testVector));
1131 // Test different strides
1133 OcclusionQueryResultsMode resultsMode[] = { RESULTS_MODE_GET, RESULTS_MODE_COPY };
1134 const char* resultsModeStr[] = { "get", "copy" };
1136 for (int resultsModeIdx = 0; resultsModeIdx < DE_LENGTH_OF_ARRAY(resultsMode); ++resultsModeIdx)
1138 OcclusionQueryResultSize resultSizes[] = { RESULT_SIZE_32_BIT, RESULT_SIZE_64_BIT };
1139 const char* resultSizeStr[] = { "32", "64" };
1141 bool testAvailability[] = { false, true };
1142 const char* testAvailabilityStr[] = { "without", "with" };
1144 for (int testAvailabilityIdx = 0; testAvailabilityIdx < DE_LENGTH_OF_ARRAY(testAvailability); ++testAvailabilityIdx)
1146 for (int resultSizeIdx = 0; resultSizeIdx < DE_LENGTH_OF_ARRAY(resultSizes); ++resultSizeIdx)
1148 const vk::VkDeviceSize resultSize = (resultSizes[resultSizeIdx] == RESULT_SIZE_32_BIT ? sizeof(deUint32) : sizeof(deUint64));
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[] =
1162 for (int strideIdx = 0; strideIdx < DE_LENGTH_OF_ARRAY(strides); strideIdx++)
1164 OcclusionQueryTestVector testVector = baseTestVector;
1165 testVector.queryResultsMode = resultsMode[resultsModeIdx];
1166 testVector.queryResultSize = resultSizes[resultSizeIdx];
1167 testVector.queryResultsAvailability = testAvailability[testAvailabilityIdx];
1168 testVector.queryResultsStride = strides[strideIdx];
1170 const vk::VkDeviceSize elementSize = (testVector.queryResultsAvailability ? resultSize * 2 : resultSize);
1172 if (elementSize > testVector.queryResultsStride)
1177 std::ostringstream testName;
1178 std::ostringstream testDescr;
1180 testName << resultsModeStr[resultsModeIdx]
1181 << "_results_size_" << resultSizeStr[resultSizeIdx]
1182 << "_stride_" << strides[strideIdx]
1183 << "_" << testAvailabilityStr[testAvailabilityIdx] << "_availability";
1185 testDescr << resultsModeStr[resultsModeIdx] << " results "
1186 << testAvailabilityStr[testAvailabilityIdx] << " availability bit as "
1187 << resultSizeStr[resultSizeIdx] << "bit variables, with stride" << strides[strideIdx];
1189 addChild(new QueryPoolOcclusionTest<OcclusionQueryTestInstance>(m_testCtx, testName.str().c_str(), testDescr.str().c_str(), testVector));